2016-07-14 3 views
4

私は正の倍数のリストとデータをグループ化するために使用される間隔を含むリストとして表されるデータを持っています。間隔は常にソートされます。私はグループに次の実装マップする任意の間隔でJava 8を使用してダブルをグループ化

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; 
    } 

でデータを試してみました
はコレクターを通じて、データを直接ロジックを実行することにより、減少/ grouppingのこの種を行うことが可能ですか?

さらに、プロセスの複雑さを考えると、2つのリスト(またはストリーム)を繰り返し処理するので、これはn^2になります。今では並列ではありませんが、パラレルでgetGroup()を実行することは可能だと思います。パフォーマンスを向上させるには、TreeSetまたはListを使用する必要があります。

+2

それは 'Iterable'インターフェイスの一部であるとして、あなたは* *ますforeachを行うために*ストリーム*する必要はありません。 –

答えて

2

TreeSet.ceiling()を使用して、「グループ」境界値を検索します。

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); 
} 

出力

-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

あなたのコードに適用することができます改善がたくさんあります。 RandomStream APIをサポートします。だから自分自身を生成する必要はありませんDoubleStream
次に境界セットを1回生成する必要があります。
最後に、あなたのために仕事をするCollector::groupingByがあります。


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; 
    } 
} 
関連する問題