Grouping java 8 objects

I have something like below:

public class MyClass { private Long stackId private Long questionId } 

A collection, say 100, where the stack can be duplicated with different questionIds. Its one-to-many relationship between stackId and questionId

Is there a way streamy , java 8 to convert to the following strcuture:

 public class MyOtherClass { private Long stackId private Collection<Long> questionIds } 

What will be a set of 25, with each instance having a nested set of 4 questionIds.

Entrance:

 [{1,100},{1,101},{1,102},{1,103},{2,200},{2,201},{2,202},{1,203}] 

Output

 [{1, [100,101,102,103]},{2,[200,201,202,203]}] 
+5
source share
3 answers

The direct path with the Stream API includes 2 stream pipelines:

  • The first creates a temporary Map<Long, List<Long>> from stackId to questionIds . This is done with the help of collectors groupingBy(classifier, downstream) , where we classify by stackId , and values โ€‹โ€‹having the same stackId are displayed on their questionId (with mapping ) and put together in a list with toList() .
  • The second converts each record of this card into an instance of MyOtherClass and collects it into a list.

Assuming you have a MyOtherClass(Long stackId, Collection<Long> questionIds) constructor MyOtherClass(Long stackId, Collection<Long> questionIds) , sample code:

 Map<Long, List<Long>> map = list.stream() .collect(Collectors.groupingBy( MyClass::getStackId, Collectors.mapping(MyClass::getQuestionId, Collectors.toList()) )); List<MyOtherClass> result = map.entrySet() .stream() .map(e -> new MyOtherClass(e.getKey(), e.getValue())) .collect(Collectors.toList()); 

Using the StreamEx library, you can do this in a single stream pipeline. This library offers pairing and first collectors. This allows you to connect two collectors and perform the finisher operation according to two collected results:

  • The first stores only the first stackId grouped elements (they will all be the same in construction)
  • The second mapping of each item in their questionId and collection into a list.
  • The finisher operation returns a new instance of MyOtherClass .

Code example:

 import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; import static one.util.streamex.MoreCollectors.first; import static one.util.streamex.MoreCollectors.pairing; // ... Collection<MyOtherClass> result = StreamEx.of(list) .groupingBy( MyClass::getStackId, pairing( collectingAndThen(mapping(MyClass::getStackId, first()), Optional::get), mapping(MyClass::getQuestionId, toList()), MyOtherClass::new ) ).values(); 
+9
source
 List<MyClass> inputs = Arrays.asList( new MyClass(1L, 100L), new MyClass(1L, 101L), new MyClass(1L, 102L), new MyClass(1L, 103L), new MyClass(2L, 200L), new MyClass(2L, 201L), new MyClass(2L, 202L), new MyClass(2L, 203L) ); Map<Long, List<Long>> result = inputs .stream() .collect( Collectors.groupingBy(MyClass::getStackId, Collectors.mapping( MyClass::getQuestionId, Collectors.toList() ) ) ); 
+2
source

You can use java8 groupingBy collector. Like this:

 import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class RandomTest { class MyClass { private Long stackId; private Long questionId; public MyClass(Long stackId, Long questionId) { this.stackId = stackId; this.questionId = questionId; } public Long getStackId() { return stackId; } public Long getQuestionId() { return questionId; } } public class MyOtherClass { private Long stackId; private Set<Long> questionIds; public MyOtherClass(Long stackId, Set<Long> questionIds) { this.stackId = stackId; this.questionIds = questionIds; } public Long getStackId() { return stackId; } public Set<Long> getQuestionIds() { return questionIds; } } @Test public void test() { List<MyClass> classes = new ArrayList<>(); List<MyOtherClass> otherClasses = new ArrayList<>(); //populate the classes list for (int j = 1; j <= 25; j++) { for (int i = 0; i < 4; i++) { classes.add(new MyClass(0L + j, (100L*j) + i)); } } //populate the otherClasses List classes.stream().collect(Collectors .groupingBy(MyClass::getStackId, Collectors.mapping(MyClass::getQuestionId, Collectors.toSet()))) .entrySet().stream().forEach( longSetEntry -> otherClasses.add(new MyOtherClass(longSetEntry.getKey(), longSetEntry.getValue()))); //print the otherClasses list otherClasses.forEach(myOtherClass -> { System.out.print(myOtherClass.getStackId() + ": ["); myOtherClass.getQuestionIds().forEach(questionId-> System.out.print(questionId + ",")); System.out.println("]"); }); } } 
0
source

Source: https://habr.com/ru/post/1246525/


All Articles