4

I want to sort elements and group them as follows, How shall I achieve that using java streams sort, group and partition by.

The input is comming in streams that means after getting the below input after sometime the input like A16,17 may come the data structure must reorganize and regroup.

Input A10, A4, A11, A3, A12,A15 ....B19,B2,B20...

Output A3-A4,A10-A12,A15,B2,B19-B20.

I could able to sort as below

array.sort(Comparator   .comparing(...)
                                .thenComparing(Comparator.comparing(...)));

but not sure how to partition and regroup for chaning input using streams in most optimised way.

 array.stream().collect(Collectors.partitionBy(...))

What should be the logic in function for partition by in above in order to achieve serial order grouping ?

1
  • It's not clear if your output should be a map of the first letter to a list of pairs, or just a list of pairs. It's also not clear how the pairing is to be performed. Also, by grouping you mean pairing, or to have one list of pairs for A, another one for B, etc? And why partitioning? It doesn't make any sense here, as there's no clear predicate to partition on. Commented Jul 6, 2017 at 18:40

1 Answer 1

1

You can do easily if you write your own Comparator and your own Collector, making use of Java8 Stream interface:

array.stream().sorted(new MyComparator()).collect(new MyCollector());

The Comparator is plain easy to write:

class MyComparator implements Comparator<String> {

    @Override
    public int compare(String s1, String s2) {
        if(s1.substring(0, 1).compareTo(s2.substring(0,1)) < 0) {
            return -1;
        } else if (s1.substring(0, 1).compareTo(s2.substring(0,1)) > 0) {
            return 1;
        } else { //first char is equal
            if(Integer.parseInt(s1.substring(1, s1.length())) < Integer.parseInt(s2.substring(1, s2.length()))) {
                return -1;
            } else if (Integer.parseInt(s1.substring(1, s1.length())) > Integer.parseInt(s2.substring(1, s2.length()))) {
                return 1;
            }
        }
        return 0;
    }
}

It basically checks for the letter at the beginning, and then checks for the numbers afterwards. Trying to use natural alphabetical order will put your A10, A11... before your A2,A3... because 1<2.

I'm leaving the Collector intentionally unwritten for you to do that part, as it is an interesting exercise.

But if you don't want to use a Collector because you find it too hard, you can always use the newly ordered List to grab its elements two by two and create another List containing the result you are looking for.

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

1 Comment

Comparator.comparingInt((String s) -> s.charAt(0)) .thenComparingInt(s -> Integer.parseInt(s.substring(1)))

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.