2015-08-31 23 views
6

मेरे पास कक्षा ए की एक सूची है, जिसमें एक सूची भी शामिल है।जावा 8 स्ट्रीम का उपयोग करके सूची की सूची को कैसे व्यवस्थित और पुन: समूहित करें?

public class A { 
    public double val; 
    public String id; 
    public List<String> names = new ArrayList<String>(); 
    public A(double v, String ID, String name) 
    { 
     val = v; 
     id = ID; 
     names.add(name); 
    } 

static public List<A> createAnExample() 
{ 
    List<A> items = new ArrayList<A>(); 

    items.add(new A(8.0,"x1","y11")); 
    items.add(new A(12.0, "x2", "y21")); 
    items.add(new A(24.0,"x3","y31")); 
    items.get(0).names.add("y12"); 
    items.get(1).names.add("y11"); 
    items.get(1).names.add("y31"); 
    items.get(2).names.add("y11"); 
    items.get(2).names.add("y32"); 
    items.get(2).names.add("y33"); 
    return items; 
} 

उद्देश्य सूची में औसत मूल्य प्रति आईडी से अधिक है। मैंने कुछ जावा 8 स्ट्रीम का उपयोग कर मुख्य समारोह में कोड जोड़ा। मेरा सवाल यह है कि मैं दूसरे ऐरे और लूप के बिना इसे और अधिक सुरुचिपूर्ण तरीके से कैसे लिख सकता हूं।

static public void main(String[] args) { 
    List<A> items = createAnExample(); 

    List<A> items2 = new ArrayList<A>(); 
    for (int i = 0; i < items.size(); i++) { 
     List<String> names = items.get(i).names; 
     double v = items.get(i).val/names.size(); 
     String itemid = items.get(i).id; 
     for (String n : names) { 
      A item = new A(v, itemid, n); 
      items2.add(item); 
     } 
    } 
    Map<String, Double> x = items2.stream().collect(Collectors.groupingBy(item -> 
      item.names.isEmpty() ? "NULL" : item.names.get(0), Collectors.summingDouble(item -> item.val))); 
    for (Map.Entry entry : x.entrySet()) 
     System.out.println(entry.getKey() + " --> " + entry.getValue()); 
} 

उत्तर

4

आप flatMap साथ यह कर सकते हैं:

x = items.stream() 
    .flatMap(a -> a.names.stream() 
     .map(n -> new AbstractMap.SimpleEntry<>(n, a.val/a.names.size())) 
    ).collect(groupingBy(
     Map.Entry::getKey, summingDouble(Map.Entry::getValue) 
    )); 

आप पाते हैं अपने आप को इस तरह की समस्याओं से निपटने अक्सर एक Map.Entry बनाने के लिए एक स्थिर विधि पर विचार करें: तो फिर तुम

static<K,V> Map.Entry<K,V> entry(K k, V v) { 
    return new AbstractMap.SimpleImmutableEntry<>(k,v); 
} 

एक कम verbose .map(n -> entry(n, a.val/a.names.size()))

1

एम में वाई फ्री StreamEx पुस्तकालय जो मानक स्ट्रीम एपीआई बढ़ाता है वहां विशेष ऑपरेशन होते हैं जो ऐसे जटिल मानचित्र बनाने में मदद करते हैं। StreamEx आपकी समस्या का उपयोग करते हुए इस तरह हल किया जा सकता:

Map<String, Double> x = StreamEx.of(createAnExample()) 
    .mapToEntry(item -> item.names, item -> item.val/item.names.size()) 
    .flatMapKeys(List::stream) 
    .grouping(Collectors.summingDouble(v -> v)); 

यहाँ mapToEntry मानचित्र प्रविष्टियां (EntryStream तथाकथित) जहां कुंजी नामों की सूची नहीं है और मूल्यों औसतन Vals हैं की धारा पैदा करता है। इसके बाद हम flatMapKeys का उपयोग मूल्यों को छोड़कर कुंजियों को फ़्लैट करने के लिए करते हैं (इसलिए हमारे पास Entry<String, Double> की स्ट्रीम है)। आखिरकार हम उन्हें दोहराने वाली चाबियों के मानों को एक साथ जोड़ते हैं।

संबंधित मुद्दे