Java 8 stream - sort by max duplicates descending

Jay :

Using Java 8 stream, I am trying to sort a list by a part of the field (groupname) maximum duplicates descending.

It only needs to use the first part before : the second part is not relevant. And the unique row records order is not relevant. (I am only trying to bring the duplicate records to top according to max duplicates.)

Test Data:

100 : 200
200 : 207
200 : 203
200 : 201
300 : 202
103 : 201
103 : 202

Expected:

200 : 207
200 : 203
200 : 201
103 : 201
103 : 202
100 : 200
300 : 202

I tried the below code, it returns the orders correctly. But only the grouped data instead of the original full records and sorted.

200=3
103=2
100=1
300=1

Java code

@Test
public void testSplit2Optimsation() {

    List<CompatibilityRule> rules = new ArrayList<>();
    CompatibilityRule compatibilityRule1 = new CompatibilityRule();
    compatibilityRule1.setGroupname("100 : 200");

    CompatibilityRule compatibilityRule2 = new CompatibilityRule();
    compatibilityRule2.setGroupname("200 : 207");

    CompatibilityRule compatibilityRule3 = new CompatibilityRule();
    compatibilityRule3.setGroupname("200 : 203");

    CompatibilityRule compatibilityRule4 = new CompatibilityRule();
    compatibilityRule4.setGroupname("200 : 201");

    CompatibilityRule compatibilityRule5 = new CompatibilityRule();
    compatibilityRule5.setGroupname("300 : 202");

    CompatibilityRule compatibilityRule6 = new CompatibilityRule();
    compatibilityRule6.setGroupname("102 : 202");

    CompatibilityRule compatibilityRule7 = new CompatibilityRule();
    compatibilityRule7.setGroupname("103 : 202");

    rules.add(compatibilityRule1);
    rules.add(compatibilityRule2);
    rules.add(compatibilityRule3);
    rules.add(compatibilityRule4);
    rules.add(compatibilityRule5);
    rules.add(compatibilityRule6);
    rules.add(compatibilityRule7);



    rules.stream()
            .map(r -> r.getGroupname().split(":")[0].trim())
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream()
            .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
            .forEach(System.out::println);

}
uneq95 :

This a working example. I hope this solves your problem.

Approach:

Grouping gives you map containing lists which you just need to sort by their sizes, then flatten them and finally collect as list.

Code:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Play {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("100 : 200",
                "200 : 207",
                "200 : 203",
                "200 : 201",
                "300 : 202",
                "103 : 201",
                "103 : 202");
        List<String> processedList = list.stream().collect(Collectors.groupingBy(string -> string.split(":")[0].trim()))
                .values().stream().sorted((list1, list2) -> Integer.compare(list2.size(), list1.size()))
                .flatMap(List::stream).collect(Collectors.toList());

        System.out.println(processedList);
    }
}

You can try to remove redundant operators, if there are any. You can access your strings using the getter methods of your class and follow the approach as shown in the example.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=139723&siteId=1