2016-07-14 17 views
4

Ich habe Daten, die als eine Liste von positiven doppelten Zahlen dargestellt wird, und eine Liste mit den Intervallen, die verwendet werden, um die Daten zu gruppieren. Das Intervall wird immer sortiert.
ich zu einer Gruppe versucht, die Daten mit der folgenden ImplementierungGruppierung Double mit Java 8 nach beliebigem Intervall zu Karte

List<Double> data = DoubleStream.generate(new Random()::nextDouble).limit(10).map(d -> new Random().nextInt(30) * d).boxed().collect(Collectors.toList()); 
    HashMap<Integer, List<Double>> groupped = new HashMap<Integer, List<Double>>(); 
    data.stream().forEach(d -> { 
     groupped.merge(getGroup(d, group), new ArrayList<Double>(Arrays.asList(d)), (l1, l2) -> { 
      l1.addAll(l2); 
      return l1; 
     }); 
    }); 
    public static Integer getGroup(double data, List<Integer> group) { 

    for (int i = 1; i < group.size(); i++) { 
     if (group.get(i) > data) { 
      return group.get(i - 1); 
     } 
    } 
    return group.get(group.size() - 1); 
} 
    public static List<Integer> group() { 
     List<Integer> groups = new LinkedList<Integer>(); 
     //can be arbitrary groupping 
     groups.add(0); 
     groups.add(6); 
     groups.add(11); 
     groups.add(16); 
     groups.add(21); 
     groups.add(26); 
     return groups; 
    } 

Ist es möglich, auf die Daten direkt die Logik dieser Art von groupping/Verringerung auszuführen, indem durch Sammler?

Zusätzlich zu der Komplexität des Prozesses sollte dies n^2 dauern, da wir über zwei Listen (oder Streams) iterieren. Jetzt ist es nicht parallel, aber ich denke, es ist möglich, getGroup() paralel durchzuführen. Irgendein Einblick sollte TreeSet oder Liste für bessere Leistung verwendet werden?

+2

Beachten Sie, dass Sie nicht brauchen, zu * Strom * a * foreach zu tun *, da es Teil der 'Iterable' Schnittstelle ist. –

Antwort

2

Verwenden Sie eine TreeSet.ceiling(), um den "Gruppen" -Begrenzungswert zu finden.

Beispiel

TreeSet<Double> groups = new TreeSet<>(); 
groups.add(5d);      // [-Inf, 5] 
groups.add(10d);      // ] 5, 10] 
groups.add(15d);      // ] 10, 15] 
groups.add(20d);      // ] 15, 20] 
groups.add(25d);      // ] 20, 25] 
groups.add(30d);      // ] 25, 30] 
groups.add(Double.POSITIVE_INFINITY); // ] 30, +Inf] 

Random rnd = new Random(); 
for (double value = 0d; value <= 30d; value += 5d) { 
    double down = Math.nextDown(value); 
    double up = Math.nextUp(value); 
    System.out.printf("%-18s -> %4s  %-4s -> %4s  %-18s -> %4s%n", 
         down, groups.ceiling(down), 
         value, groups.ceiling(value), 
         up, groups.ceiling(up)); 
} 
for (int i = 0; i < 10; i++) { 
    double value = rnd.nextDouble() * 30d; 
    double group = groups.ceiling(value); 
    System.out.printf("%-18s -> %4s%n", value, group); 
} 

Ausgabe

-4.9E-324   -> 5.0  0.0 -> 5.0  4.9E-324   -> 5.0 
4.999999999999999 -> 5.0  5.0 -> 5.0  5.000000000000001 -> 10.0 
9.999999999999998 -> 10.0  10.0 -> 10.0  10.000000000000002 -> 15.0 
14.999999999999998 -> 15.0  15.0 -> 15.0  15.000000000000002 -> 20.0 
19.999999999999996 -> 20.0  20.0 -> 20.0  20.000000000000004 -> 25.0 
24.999999999999996 -> 25.0  25.0 -> 25.0  25.000000000000004 -> 30.0 
29.999999999999996 -> 30.0  30.0 -> 30.0  30.000000000000004 -> Infinity 
3.7159199611763514 -> 5.0 
7.685306184937567 -> 10.0 
2.6949924484301633 -> 5.0 
17.594251973883363 -> 20.0 
24.005899441664994 -> 25.0 
7.720531186142164 -> 10.0 
22.82402791692674 -> 25.0 
22.68288732263466 -> 25.0 
13.056624829892243 -> 15.0 
8.504511505971251 -> 10.0 
5

Es gibt viele Verbesserungen, die Sie auf Ihren Code anwenden können. Random unterstützt Stream API. Also keine Notwendigkeit, eigene DoubleStream zu generieren.
Als nächstes sollten Sie Ihre Grenze nur einmal erstellen.
Letzte Sache, es gibt eine Collector::groupingBy, die die Arbeit für Sie erledigt.


import java.util.List; 
import java.util.Map; 
import java.util.NavigableSet; 
import java.util.Random; 
import java.util.TreeMap; 
import java.util.TreeSet; 
import java.util.stream.Collectors; 

public class Test { 

    public static void main(String... args) { 
    Random r = new Random(); 
    List<Double> data = r.doubles(10).map(d -> r.nextInt(30) * d).peek(System.out::println).boxed() 
     .collect(Collectors.toList()); 
    NavigableSet<Integer> groups = group(); 
    Map<Integer, List<Double>> groupped = data.stream() 
     .collect(Collectors.groupingBy(d -> groups.floor(d.intValue()), TreeMap::new, Collectors.toList())); 
    System.out.println(groupped); 
    } 

    public static NavigableSet<Integer> group() { 
    NavigableSet<Integer> groups = new TreeSet<>(); 
    groups.add(0); 
    groups.add(6); 
    groups.add(11); 
    groups.add(16); 
    groups.add(21); 
    groups.add(26); 
    return groups; 
    } 
}