I am reading in a .csv
file sort of like a spreadsheet in excel. There are a certain number of columns, determined by the file, and I read each line into a stri开发者_如何转开发ng array using the .split(",")
method. I then put this into an array list so it can hold all of the string arrays without giving it a specific size. However, when I go to sort the array list using Collections.sort()
, the program breaks. What could the problem be? Here is my code to sort:
Collections.sort(stringList, new Comparator < String[] > () {
public int compare(String[] strings, String[] otherStrings) {
return -1 * (strings[sortNum].compareTo(otherStrings[sortNum]));
}
});
Two points:
- Don't multiply the result of
compare
by -1 to reverse a comparison.Integer.MIN_VALUE * -1
is stillInteger.MIN_VALUE
. Instead, reverse the order of the comparison itself - My guess is that you've actually got some rows without enough columns. Perhaps you should put those at the end?
Something like:
Collections.sort(stringList, new Comparator < String[] > () {
public int compare(String[] x1, String[] x2) {
if (x1.length > sortNum && x2.length > sortNum) {
return x2[sortNum].compareTo(x1[sortNum]);
}
if (x1.length > sortNum) {
return 1;
}
if (x2.length > sortNum) {
return -1;
}
return x2.length - x1.length;
}
});
Alternatively, filter your list first to make absolutely sure that all rows have enough columns.
Well, either strings[sortNum] or otherStrings[sortNum] could be out of bounds. You need to do some checks to prevent that. Also, strings[sortNum] or otherStrings[sortNum] could be null. I bet you're running into one of these 2 things. What does the call stack indicate?
Try using this
First your class comparator with a constructor:
public class MyStringArrayComparator implements Comparator<String[]>{
Integer sortNum;
public MyStringComparator(Integer index) {
sortNum = index;
}
@Override
public int compare(String[] strings, String[] otherStrings) {
return -1*(strings[sortNum].compareTo(otherStrings[sortNum]));
}
}
and in your code
Collections.sort(stringList,new MyStringArrayComparator<String[]>(index));
Hope that works for you
Sharing code in case someone need to do the sort on multiple columns.
public final class ArrayComparatorWithIndex<T extends Comparable<T>> implements Comparator<T[]>
{
private final int[] indexToSort;
public ArrayComparatorWithIndex(int[] indexToSort)
{
if(indexToSort == null || indexToSort.length == 0){
throw new IllegalArgumentException("Index to use for sorting cannot be null or empty.");
}
this.indexToSort = indexToSort;
}
@Override
public int compare(T[] str, T[] otherStr)
{
int result= 0;
for (int index : indexToSort)
{
result= str[index].compareTo(otherStr[index]);
if (result != 0){
break;
}
}
return result;
}
}
//Example how to use it:
int[] indexForSorting= new int[] { 1, 3 };
Collections.sort(stringList, new ArrayComparatorWithIndex<String>(indexForSorting));
I suspect you might have a closure problem in reference to the 'sortNum' variable. See Jon Skeet's closure article for some guidance, even though it deals with closures in C# it should still be relevant. Even if you don't have this issue, it's a good read. :)
you can provide default values for empty "cells":
public int compare(String[] strings, String[] otherStrings) {
String one, other;
one = other = ""; // default value
if (sortNum<strings.length && strings[sortNum] != null) {
one = strings[sortNum];
}
if (sortNum<otherStrings.length && otherStrings[sortNum] != null) {
other = otherStrings[sortNum];
}
return -1 * (one.compareTo(other));
}
精彩评论