Guforu
Guforu

Reputation: 4023

Sort by multiple columns, Java 8

Consider the following table:

Name Code Number
Mike x6   5.0
Mike b4   3.0
Mike y2   1.0
Tom  y2   4.5
Tom  x6   4.5
Tom  b4   1.0
Susi x6   4.0
Susi y2   3.0
Susi b4   2.0

I have three columns, it should be sorted first of all by the column "Name" and then by the column "Number". I wanted to do this with Dictionary (use String array as value and Double as key) and then sort by value, but I miss the sort by the name.

Map<Double, String[]> map = new HashMap<Double, String[]>();
map.put(5.0, {"Mike", "x6"});
System.out.println(map.get(5.0));

I don't know what is the best way to store my data. I would like also to know the solution in Java 8.

Upvotes: 3

Views: 3630

Answers (2)

Tunaki
Tunaki

Reputation: 137084

First of all, you should make each line of your table an object:

public class MyData {

    private String name;
    private String code;
    private Double number;

    public MyData(String name, String code, Double number) {
        this.name = name;
        this.code = code;
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public String getCode() {
        return code;
    }

    public Double getNumber() {
        return number;
    }

}

Using Map<Double, String[]> does not represent what you are trying to achieve. A Map is used to create a link between an unique key an a value. Does it make sense for each number to be associated to a name and a code?

Once you have this object, it is much easier to sort it according to its properties:

List<MyData> list = new ArrayList<>();
list.add(new MyData("Mike", "x6", 5.0));
list.add(new MyData("Mike", "b4 ", 3.0));
list.add(new MyData("Mike", "y2", 1.0));
list.add(new MyData("Tom", "y2", 4.5));
List<MyData> sortedList = list.stream()
                              .sorted(Comparator.comparing(MyData::getName).thenComparing(MyData::getNumber))
                              .collect(Collectors.toList());

Upvotes: 8

Philipp Lengauer
Philipp Lengauer

Reputation: 1959

I think a Map is the wrong data structure for your case, as Maps explicitly DO NOT DEFINE an order based on the values.

But you may help yourself with streams. Something like:

map.entrySet().stream().sorted((e1, e2) -> e1.getValue()[0].compareTo(e2.getValue()[0])).map(e -> e.getKey()).toArray(l -> new Integer[l])

this will give you an array of keys, sorted by the first integer in the value array. the full value you may then look up in the original map.

Upvotes: 2

Related Questions