如何对包含空元素的对象数组进行排序?

Posted

技术标签:

【中文标题】如何对包含空元素的对象数组进行排序?【英文标题】:How to sort an array of objects containing null elements? 【发布时间】:2015-02-17 19:15:38 【问题描述】:

在我的程序中,创建了一个固定长度 [7] 的对象数组fClasses,每个对象都是一个类FClass,其中包含3 个Strings、一个int 和一个int[]。这些值从 .txt 文件中读取,并根据int 的值添加到数组的特定索引中。 .txt 文件中的条目比数组中的索引少,因此数组最终看起来像这样:

fClasses[0]  str1, str2, str3, int1, int [] 1,2,3,4,5
fClasses[1]  str1, str2, str3, int1, int [] 1,2,3,4,5
fClasses[2]  str1, str2, str3, int1, int [] 1,2,3,4,5
fClasses[3] null
fClasses[4] null
fClasses[5]  str1, str2, str3, int1, int [] 1,2,3,4,5
fClasses[6]  str1, str2, str3, int1, int [] 1,2,3,4,5

稍后在程序中,我需要根据int[] 中的ints 的平均值对数组进行排序。我有一个工作方法来返回它,但是当我尝试使用 compareToArrays.sort 对数组进行排序时,我得到了一长串以这些开头的错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at java.util.ComparableTimSort.countRunAndMakeAscending(Unknown Source)
    at java.util.ComparableTimSort.sort(Unknown Source)
    at java.util.Arrays.sort(Unknown Source)
    at FProg.sortClasses(FProg.java:228)

我的compareTo 方法如下所示,它位于实现Comparable 的类中:

public int compareTo(FClass other) 

    if (other == null || this.avg == other.avg)
    
        return 0;
    
    else if (this.avg < other.avg)
    
        return -1;
    
    else
    
        return 1;
    


我正在尝试调用此方法进行排序:

public void sortClasses()

    Arrays.sort(fClasses, 0, MAX_CLASSES);

我已经使用包含足够条目来填充数组的 .txt 文件对其进行了测试,并且在这种情况下排序工作正常,所以我相信我遇到的问题是我的排序方法无法对数组进行排序其中的空元素。有什么办法可以实现吗?

【问题讨论】:

【参考方案1】:

使用 Java 8,您可以轻松构建所需的比较器:

Arrays.sort(fClasses, Comparator.nullsFirst(Comparator.naturalOrder()));

当然,如果这是您想要的,请使用 nullsLast

【讨论】:

【参考方案2】:

您需要自己的 Comparator 实现并检查空值并返回 0

 Arrays.sort(fClasses, new Comparator<FClass>() 
    @Override
    public int compare(FClass o1, FClass o2) 
        if (o1 == null && o2 == null) 
            return 0;
        
        if (o1 == null) 
            return 1;
        
        if (o2 == null) 
            return -1;
        
        return o1.compareTo(o2);
    );

【讨论】:

不应该 o1 == null 返回 -1,因为 null 值意味着它的重要性低于实际有值的 o2【参考方案3】:

您必须创建一个Comparator&lt;FClass&gt;,而不是使用Comparable&lt;FClass&gt;

public class FClassComparator implements Comparator<FClass> 

    public int compare(FClass left, FClass right) 
        // Swap -1 and 1 here if you want nulls to move to the front.
        if (left == null) return right == null ? 0 : 1;
        if (right == null) return -1;
        // you are now guaranteed that neither left nor right are null.

        // I'm assuming avg is int. There is also Double.compare if they aren't.
        return Integer.compare(left.avg, right.avg); 
    

然后调用排序方式:

Arrays.sort(fClassArray, new FClassComparator());

【讨论】:

【参考方案4】:

使用Apache Commons Collections 4,您可以使用ComparatorUtils 来做到这一点:

Collections.sort(arr, ComparatorUtils.nullLowComparator(ComparatorUtils.NATURAL_COMPARATOR));

【讨论】:

【参考方案5】:

通过导入org.apache.commons.collections.comparators 包 Apache 2.1.1 Release 库,我可以使用NullComparator 作为Collections.sort() 方法的第二个参数对列表进行排序,例如ArrayList&lt;String&gt;,如下所示:

ArrayList<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list.add("baz");
list.add(null);

// Sort the list
Collections.sort(list, new NullComparator(true));

System.out.println(list);
// outputs:
// [bar, baz, foo, null]

我喜欢这种方法的一点是 NullComparator 有一个重载构造函数,它允许您指定是否希望 null 被视为高值或低值,这对我来说似乎很直观。

NullComparator(boolean nullsAreHigh)

希望这对某人有所帮助!

【讨论】:

以上是关于如何对包含空元素的对象数组进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

具有未定义和空值的排序对象数组

如何根据GPA对数组列表进行升序排序? arraylist 包含一个对象数组。 (Java)[重复]

如何在 Java 中对对象数组进行排序?

按对象属性对 javascript 对象数组进行排序

JS对象数组多条件排序

java 对象数组排序的问题,急急急急