2015-10-01 2 views
4

У меня есть список объектов Ob определяется какУменьшают коллекцию объектов по общему полю в Java-8

class Ob { 
    private String type; 
    private List<String> attire; 
    // standard getter and setters 

    public Ob (String type){ 
     this.type=type; 
    } 

    public Ob addAttrire(String att){ 
     if(attire == null){ 
      attire = new ArrayList<>(); 
     } 
     attire.add(att); 
     return this; 
    } 
} 

я получаю объекты как

[{ 
"type" : "upper" 
attires : [{"t1","t2"}] 
}, 
{ 
"type" : "upper" 
attires : ["t3","t4"] 
}, 
{ 
"type" : "lower" 
attires : ["l1","l2"] 
}] 

, который я должен сочетать в

[{ 
"type" : "upper" 
attires : ["t1","t2","t3","t4"] 
},{ 
"type" : "lower" 
attires : ["l1","l2"] 
}] 

Как использовать поток для этого. Уменьшает помощь? Поток можно использовать,

List<Ob> coll = new ArrayList<>(); 


coll.add(new Ob("a").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("a").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("a").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("b").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("b").addAttrire("1").addAttrire("2").addAttrire("3")); 
     coll.add(new Ob("b").addAttrire("1").addAttrire("2").addAttrire("3")); 



Collection<Ob> values = coll.stream() 
       .collect(toMap(Ob::getType, Function.identity(), (o1, o2) -> { 
        o1.getAttire().addAll(o2.getAttire()); 
        return o1; 
       })).values(); 

Обновленный вопрос с раствором Ruben. Нет необходимости удалять дубликаты, но это можно сделать, используя набор в Ob для наряда. Нынешнее решение работало безупречно.

+0

О ваш комментарий на Rubens ответ «* Что рекомендуемый способ в таком случае с влиянием на производительность *» Я думаю, что в нет большой разницы в производительности исполнения. Если производительность оказывается проблемой, я думаю, что лучше переписать код, используя цикл, который даст вам больше контроля. Я думаю, что решение Rubens имеет преимущество, потому что оно немного короче и проще. Я считаю, что у меня есть преимущество, потому что оно не изменяет оригинальные «Ob's» и, следовательно, более функционально. – Lii

ответ

3

Вы можете собрать toMap с функцией слияния, которая сливает списки

Collection<Ob> values = coll.stream() 
    .collect(toMap(Ob::getType, Function.identity(), (o1, o2) -> { 
     o1.getAttire().addAll(o2.getAttire()); 
     return o1; 
    })).values(); 
+0

Это не удаляет повторяющиеся строки наряд и возвращает коллекцию, поддерживаемую экземпляром 'HashMap', из' toMap', поэтому я не думаю, что он полностью отвечает на вопрос. Иначе это умно! – Lii

+1

@Lii Удаление дубликатов может быть тем, чего хочет _rohit_, но в этом вопросе не найти ничего, поэтому я его оставил. Код не возвращает 'HashMap', а' Collection' (см. '.values ​​()' в конце). – Ruben

+0

О, нет на самом деле ничего об удалении дубликатов в вопросе! Я, кажется, неправильно понял пример раньше, сожалею об этом. Что касается коллекции, я имею в виду, что метод 'values' возвращает коллекцию, которая * поддерживается * картой, созданной' toMap'. – Lii

3

Это решение использует groupingBy коллектор, а затем отдельный шаг, который создает новый Ob, который является результатом слияния всех Ob S, которые имеют один и тот же type.

Я думаю, что решение Rubens имеет преимущество перед этим ответом, потому что оно немного короче и проще. Я думаю, что этот ответ имеет преимущество, потому что он не изменяет оригинал Ob и, следовательно, более функциональный.

public static void testTrickyStreamSet() { 
    Stream<Ob> s = Stream.of(
     new Ob("a", "1", "2"), 
     new Ob("b", "1", "4"), 
     new Ob("a", "1", "3"), 
     new Ob("b", "1", "5")); 

    List<Ob> os = s.collect(groupingBy(o -> o.type)) 
     .entrySet().stream() 
     .map(e -> new Ob(e.getKey(), 
      e.getValue().stream().flatMap(o -> o.attire.stream()).collect(toList()))) 
     .collect(toList()); 

    // Prints [<Ob type=a, attire=[1, 2, 3]>, <Ob type=b, attire=[1, 4, 5]>] 
    System.out.println(os); 
} 

public static class Ob { 
    public String type; 
    public List<String> attire; 

    public Ob(String type, String... attire) { 
     this.type = type; 
     this.attire = Arrays.asList(attire); 
    } 

    public Ob(String type, List<String> attire) { 
     this.type = type; 
     this.attire = new ArrayList<>(attire); 
    } 

    @Override 
    public String toString() { 
     return "<Ob type=" + type + ", attire=" + attire + ">"; 
    } 
} 
Смежные вопросы