问题
In my program an array fClasses
of fixed length [7] of objects is created, each object is a class FClass
that contains 3 Strings
, an int
, and an int[]
. These values are read from a .txt file and added to a specific index of the array based on the value of the int
. There are less entries in the .txt file then there are indices in the array so the array ends up looking something like this:
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}}
Later in the program I need to sort the array based on the average of the ints
in the int[]
. I have a working method to return this but when I try to sort the array using compareTo
and Arrays.sort
I get a long list of errors starting with these:
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)
My compareTo
method looks like this and it\'s located in a class that implements 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;
}
}
And I\'m trying to call this method to do the sorting:
public void sortClasses()
{
Arrays.sort(fClasses, 0, MAX_CLASSES);
}
I have tested it with a .txt file that contains enough entries to fill the array and the sort works correctly in that case, so I believe the problem I\'m having is that my sort method can\'t sort an array with null elements in it. Is there any way this can be achieved?
回答1:
You need your own Comparator
implementation and check for nulls and return 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);
}});
回答2:
Using Java 8, you can easily build the comparator you need:
Arrays.sort(fClasses, Comparator.nullsFirst(Comparator.naturalOrder()));
Use nullsLast
instead if that's what you want, of course.
回答3:
You have to create a Comparator<FClass>
, rather than use a Comparable<FClass>
.
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);
}
}
Then call sort via:
Arrays.sort(fClassArray, new FClassComparator());
回答4:
With Apache Commons Collections 4 you can use ComparatorUtils to do that:
Collections.sort(arr, ComparatorUtils.nullLowComparator(ComparatorUtils.NATURAL_COMPARATOR));
回答5:
By importing the org.apache.commons.collections.comparators package of the
Apache 2.1.1 Release library, I'm able to sort a list, such as an ArrayList<String>
, using the NullComparator
as the second argument of the Collections.sort()
method, as follows:
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]
The thing I like about this approach is that the NullComparator
has an overload constructor which allows you to specify whether you want null
to be considered a high value or a low value, which seems pretty intuitive to me.
NullComparator(boolean nullsAreHigh)
Hope this helps someone!
来源:https://stackoverflow.com/questions/27556104/how-to-sort-an-array-of-objects-containing-null-elements