DPM
DPM

Reputation: 2030

Encapsulating Collection to Map transformation using Java 8's streams and collectors into a method

I believe this question is not a duplicate despite the numerous questions about converting lists to maps in Java 8. Please bear with me.

What I'm trying to do is gradually building a library of functions for myself to avoid having to repeat convoluted coded over and over involving streams and collectors, which tend to be much too verbose.

At the moment I'm stuck in creating a method that transforms a collection into a map grouping by some field of the object of the collection.

Let's say we have this class:

   class SomeClass {
      private String someField;
      private String anotherfield;

      public String getSomeField() {
         return someField;
      }
      public String getAnotherField() {
         return anotherfield;
      }
   }

And a list:

  List<SomeClass> myList = new ArrayList<SomeClass>();
  //populate the list...

And we want this, where each key of the map is a unique value for someField in the objects of the list:

Map<String,List<SomeClass>> myMap;

Which can be done like this:

 Map<String,List<SomeClass>> myMap = 
    myList.stream().collect(Collectors.groupingBy(o -> o.getSomeField()  ));

Here's the part that I can't solve. As I said I want to hide this into a cleaner method in a utility class that I intend to use in my projects. The method's signature:

   public static <T, R> Map<R, List<T>> collectionToMap(
      Collection<T> coll, Function<? super T, ? extends R> groupByKey)

Which would be called like:

Map<String,List<SomeClass>> amap = collectionToMap(myList, o -> o.getSomeField());

Here is a clumsy attempt that doesn't compile, but just to give you an idea:

   public static <T, R> Map<R, List<T>> collectionToMap(Collection<T> coll, Function<? super T, ? extends R> groupByKey) {
      Map<R,List<T>> amap = coll.stream().collect(Collectors.groupingBy( 
            T::groupBy,
            Collectors.mapping(T, Collectors.toList())
            ));
      return amap;
   }

I can't wrap my head around it.

Upvotes: 3

Views: 293

Answers (1)

Eran
Eran

Reputation: 393781

You don't need mapping. You just have to pass the groupByKey Function to groupingBy:

public static <T, R> Map<R, List<T>> collectionToMap(Collection<T> coll, Function<? super T, ? extends R> groupByKey) {
    return coll.stream().collect(Collectors.groupingBy(groupByKey));
}

Upvotes: 4

Related Questions