2016-10-13 10 views
5

ファイルを解析し、いくつかの基本的なフィルタリングに基づいて結果をコレクションに格納するJavaラムダストリームがあります。異なるコレクションへのJava Lambdaストリーム

私はちょうどラムダを学んでいるので、これはばかげて悪い場合はここで私と一緒にクマ。しかし、私の間違いを指摘してください。指定したファイルについては

#ignored 
this 
is 
#ignored 
working 
fine 

コード:

List<String> matches; 

Stream<String> g = Files.lines(Paths.get(givenFile)); 

matches = g.filter(line -> !line.startsWith("#")) 
      .collect(Collectors.toList()); 

["this", "is", "working", "fine"] 

、私はこの同じストリーム内の第2のリストに無視行を収集については行くだろうか?以下のようなもの:私は新しいストリームを開くことが非常に簡単になり実現

List<String> matches; 
List<String> ignored; // to store lines that start with # 

Stream<String> g = Files.lines(Paths.get(exclusionFile.toURI())); 

matches = g.filter(line -> !line.startsWith("#")) 
      // how can I add a condition to throw these 
      // non-matching lines into the ignored collection? 
      .collect(Collectors.toList()); 

は、ロジックビット、および.collect()簡単に十分な無視の行を変更します。しかし、私は1つのストリームですべてを行うことができれば、このファイルを2回ループする必要はありません。代わりに、二つの流れの

+0

これは 'g.filter(..)。map(t-> t :: toString))。collect(.. toList())' –

+0

のようなものでなければなりません。最後の例をOracle docs:https: //docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html – Gene

答えて

13

あなたはコレクタにpartitioningByを使用することができます

List<String> strings = Arrays.asList("#ignored", "this", "is", "#ignored", "working", "fine"); 
Map<Boolean, List<String>> map = strings.stream().collect(Collectors.partitioningBy(s -> s.startsWith("#"))); 
System.out.println(map); 

ここで出力

{false=[this, is, working, fine], true=[#ignored, #ignored]} 

私はBooleanとしてキーを使用していますが、意味のある文字列または列挙

にそれを変更することができます編集

文字列がいくつかの他の特殊文字で始まることができれば、あなたはまた、

{!=[!Someother], #=[#ignored, #ignored], *=[*star], others=[this, is, working, fine]} 

groupingBy

List<String> strings = Arrays.asList("#ignored", "this", "is", "#ignored", "working", "fine", "!Someother", "*star"); 
    Function<String, String> classifier = s -> { 
     if (s.matches("^[[email protected]#$%^&*]{1}.*")) { 
      return Character.toString(s.charAt(0)); 
     } else { 
      return "others"; 
     } 
    }; 
    Map<String, List<String>> maps = strings.stream().collect(Collectors.groupingBy(classifier)); 
    System.out.println(maps); 

出力を使用することができますが、私はあなたが来る可能性が最も近いと思う巣groupingBypartitioningBy

+1

これは素晴らしく、感謝しました。 – AWT

1

をすることができますこれに対する一般的なアプローチは、peekのようになります。

g.peek(line -> if (line.startsWith("#")) { 
    ignored.add(line); 
}) 
.filter(line -> !line.startsWith("#")) 
// how can I add a condition to throw these 
// non-matching lines into the ignored collection? 
.collect(Collectors.toList()); 

パーティショニングとは違って、少なくとも理論的には、多くとも一緒に変更することができますが、多くの場合peekが必要です。しかし、わかるように、論理を複製する必要があります。理想的ではありません。

関連する問題