简体   繁体   中英

Java Stream - Create a Map of Sorted Duplicates

I have a list of objects and some of these objects share a similar ID, however the rest of the attributes are different. I know how to group them by similar IDs...

...
.stream()
.collect(groupingBy(obj -> obj.id, mapping(obj -> obj, toList())));

However I want to add an extra layer of logic. I want each List in the Map to be sorted by two conditions.

First condition, I want to check whether the obj.specialId exists within a separate Set using contains . If it doesn't, that's fine, but if it does then I want that object to be first in the Set . Something like specialSet.contains(obj.specialId) .

Second condition is that I want to have them sorted by date. The objects have an attribute called date, obj.date .

The conditions are not really important, what I'm most confused about is how to preserve the order of the values in my Map . Once I know how to do that, it should be easy to add the conditions I want.

From what I can understand, you will need to switch from using set to using list to be able to keep the order between the elements. Then you need three basic pieces of code:

  1. A classifier such as this lambda: Thing::getId , that means using the id to group them.
  2. A supplier expression for data structure, a map is the easiest way to go: HashMap::new .
  3. A Collector to work on the grouped elements something like Collectors.collectingAndThen(...)

A complete exemple:

public class Sandbox {


    public static <T> List<T> doThingWithList( List<T> list) {
        /**
         * Do some fancy things on your grouped elements
         * Such as sorting them
         */
        return list;
    }

    public static void main(String[] args){
        List<Thing> things = new ArrayList<>();
        things.add(new Thing(1,"first", "first ever"));
        things.add(new Thing(2,"second", "almost got first place"));
        things.add(new Thing(2,"second","sharing the second place is better than finishing third"));

        Map<Integer,List<Thing>> result = things.stream()
                .collect(
                        Collectors.groupingBy(Thing::getId, HashMap::new,
                                Collectors.collectingAndThen(Collectors.toList(), Sandbox::doThingWithList))
                );
        System.out.println(result);
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM