fork(2) download
  1. import java.util.*;
  2. import java.util.stream.*;
  3.  
  4. /* Name of the class has to be "Main" only if the class is public. */
  5. public class Main {
  6.  
  7. static List<Foo> joinedCategoriesMap(List<Foo> input) {
  8. return input
  9. .stream()
  10. .collect(Collectors.groupingBy(Foo::getId))
  11. .entrySet().stream()
  12. .map(e -> new Foo(
  13. e.getKey(),
  14. e.getValue().get(0).name,
  15. e.getValue().stream().map(Foo::getCategory).collect(Collectors.toList()))
  16. )
  17. .collect(Collectors.toList());
  18. }
  19.  
  20. static List<Foo> joinedCategoriesReduce(List<Foo> input) {
  21. return input
  22. .stream()
  23. .collect(Collectors.groupingBy(Foo::getId)) // Map<Integer, List<Foo>>
  24. .entrySet().stream()
  25. .map(e -> e.getValue().stream() // Stream<Foo>
  26. .reduce(new Foo(e.getKey(), e.getValue().get(0).getName(), (String)null), Foo::merge)
  27. )
  28. .collect(Collectors.toList());
  29. }
  30.  
  31. public static void main (String[] args) throws java.lang.Exception {
  32. final Foo f1 = new Foo(1L, "a", "c1");
  33. final Foo f2 = new Foo(1L, "a", "c2");
  34. final Foo f3 = new Foo(2L, "a", "c1");
  35.  
  36. final List<Foo> li = List.of(f1, f2, f3);
  37.  
  38. System.out.println("Map: ");
  39. joinedCategoriesMap(li).forEach(System.out::println);
  40.  
  41. System.out.println("Reduce: ");
  42. joinedCategoriesReduce(li).forEach(System.out::println);
  43. }
  44.  
  45. static class Foo {
  46. private Long id;
  47. private String name;
  48. private String category;
  49. private List<String> categories;
  50.  
  51. Foo(Long id, String name, String cat) {
  52. this.id = id;
  53. this.name = name;
  54. this.category = cat;
  55. }
  56.  
  57. Foo(Long id, String name, List<String> cats) {
  58. this.id = id;
  59. this.name = name;
  60. this.categories = cats;
  61. }
  62.  
  63. static Foo merge(Foo accum, Foo other) {
  64. if (null == accum.categories) {
  65. accum.categories = new ArrayList<>();
  66. if (null != accum.category) {
  67. accum.categories.add(accum.category);
  68. accum.category = null;
  69. }
  70. }
  71. accum.categories.add(other.category);
  72.  
  73. return accum;
  74. }
  75.  
  76. public Long getId() { return id; }
  77. public void setId(Long id) { this.id = id; }
  78.  
  79. public String getName() { return name; }
  80. public void setName(String name) { this.name = name; }
  81.  
  82. public String getCategory() { return category; }
  83.  
  84. @Override
  85. public String toString() {
  86. return String.format("Foo { id=%d, name=%s, category=%s, categories=%s }", id, name, category, categories);
  87. }
  88. }
  89. }
Success #stdin #stdout 0.15s 34784KB
stdin
Standard input is empty
stdout
Map: 
Foo { id=1, name=a, category=null, categories=[c1, c2] }
Foo { id=2, name=a, category=null, categories=[c1] }
Reduce: 
Foo { id=1, name=a, category=null, categories=[c1, c2] }
Foo { id=2, name=a, category=null, categories=[c1] }