0

I have a function which reads a CSV file and after some processing put the data into an ArrayList<ArrayList<String>>.

So I have this:

  ArrayList = list of rows
  sub-ArrayList<String> = list of columns

Now I have to do this (I'm guessing the java way of doing this is to use a Comparator): I need to sort these rows according to the string values of each field.

So, for example, if I have the rows (where each field is the final String in the ArrayList<ArrayList<String>> structure):

Name|Birthdate|FathersName
John,2001-01-01,Steven
John,2001-01-01,Albert

the sorting action should reverse these two rows (because the first 2 fields are equal so the third field determines the order).

Any tips on how to do this would be greatly appreciated.

Answer: Arnaud Denoyelle's answer led me to the following generic solution

private Comparator<List<String>> comparator = new Comparator<List<String>>() {
      @Override
      public int compare(List<String> list1, List<String> list2) {
          int size = list1.size();
          int diff = 0;
          for (int i=0; i<size; i++) {
              diff = list1.get(i).compareTo(list2.get(i));
              if (diff != 0) {
                  break;
              }
          }
          return diff;
      }
};

Note: this assumes that the rows being compared have the same number of columns, which in my case is a valid assumption.

user13955
  • 860
  • 2
  • 9
  • 25
  • 1
    Yes, Comparator is the right way to do this. Then, if you want to painlessly write a Comparator, you can do it in this way : `Comparator.comparing(firstCriteria).thenComparing(secondCriteria)` etc. – Arnaud Denoyelle Mar 19 '15 at 11:36

5 Answers5

3

You want to use comparators. On the other hand, if you columns are always the same and a fixed number (as in your example), your could create a class Person, extend Comparable and have an ArrayList<Person> which in general is better. Especially for instance if you want those dates to be actual Date objects and not Strings.

Daniel Langdon
  • 5,899
  • 4
  • 28
  • 48
  • +1 because you propose to create a class Person, which is the right thing to do in this case. If you can have typed data, do it. – user2336315 Mar 19 '15 at 11:46
1

Yes, Comparators are the way to sort your list. As you are sorting a List<List<String>>, you need a Comparator<List<String>>.

In Java < 8, create an anonymous implementation of Comparator :

Comparator<List<String>> comparator = new Comparator<List<String>>() {
  @Override
  public int compare(List<String> o1, List<String> o2) {
    int diff = o1.get(0).compareTo(o2.get(0));
    if (diff == 0) {
      diff = o1.get(1).compareTo(o2.get(1));
      if (diff == 0) {
        diff = o1.get(2).compareTo(o2.get(2));
      }
    }
    return diff;
  }
};

From Java 8, you can write it easier :

Comparator<List<String>> comparator =
    Comparator.comparing((List<String> l) -> l.get(0))
        .thenComparing((List<String> l) -> l.get(1))
        .thenComparing((List<String> l) -> l.get(2));

Then sort :

Collections.sort(list, comparator);
Arnaud Denoyelle
  • 29,980
  • 16
  • 92
  • 148
0

You should consider using a container the sorts automatically such as TreeMap or 'TreeSet'.

http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html

You can customise the sorting by implementing the Comparator interface for your own need.

APD
  • 1,459
  • 1
  • 13
  • 19
0

Java version < 8: could use Comparator and Collections.sort()

Java version >= 8: could use Lambda Expressions

S. Pauk
  • 5,208
  • 4
  • 31
  • 41
0

This is a java sample with a generic Comparator>

package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ArrayListComparator {

    public static void main(String[] args) {
        ArrayList<String> one=new ArrayList<>();
        one.add("John");one.add("2001-01-01"); one.add("Steven");
        ArrayList<String> two=new ArrayList<>();
        two.add("John");two.add("2001-01-01"); two.add("Albert");
        List<ArrayList<String>> container=new ArrayList<ArrayList<String>>();
        container.add(one);
        container.add(two);
        Collections.sort(container, new ArrayComparator());
        System.out.println(container.get(0).get(2));


    }

    public static class ArrayComparator implements Comparator<List<String>> {

        @Override
        public int compare(List<String> o1, List<String> o2) {
            if (o1!=null && o2!=null) {
                for (int index=0; index<o1.size(); index++ ) {
                    if (index<o2.size()) {
                        String o1Element=o1.get(index);
                        String o2Element=o2.get(index);
                        if (o1Element!=null) {
                            int result=o1Element.compareTo(o2Element);
                            if (result!=0) {
                                return result;
                            }
                        } else {
                            return -1;
                        }
                    } else {
                        return 1;
                    }
                }
                if (o2.size()>o1.size()) {
                    return -1;
                }
                return 0;
            }
            if (o1==null && o2!=null) {
                return -1;
            }
            if (o1!=null && o2==null) {
                return 1;
            }           
            return 0;
        }

    }

}

As stated by others with java 8 you could use lambda expression.

Giovanni
  • 3,951
  • 2
  • 24
  • 30