6

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 string 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]));
    }
});
7
  • 1
    Where does sortNum come from? Commented Sep 6, 2011 at 16:05
  • 2
    What do you mean by "breaks"? Where doesn't it break? What error do you get? What did you expect to happen? Does every row have sortNum+1 cells? Commented Sep 6, 2011 at 16:06
  • Are you sure that sortNum is not out of the bounds of either String[]? Commented Sep 6, 2011 at 16:07
  • I assume sortNum is the column number you want to reverse sort by. I also assume its a String which you want to have ASCIIbetical sorting on. Commented Sep 6, 2011 at 16:07
  • how does it break? Do you have a stack trace? Commented Sep 6, 2011 at 16:07

6 Answers 6

7

Two points:

  • Don't multiply the result of compare by -1 to reverse a comparison. Integer.MIN_VALUE * -1 is still Integer.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.

Sign up to request clarification or add additional context in comments.

Comments

1

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?

Comments

1

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

Comments

1

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));

Comments

0

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. :)

Comments

0

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));
            }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.