bugfix> java > 投稿

例に基づいて、Java8ストリームを使用して文字列内の一意の文字を検索する関数をコーディングしましたここに。

私にとって、それはかなり直感的ではありません。おそらく私はまだストリームを学んでいるからでしょう。これを読みやすくする方法はありますか?

コードは次のとおりです。

   public static void main(String[] args) {
        String str = "aabcddeffg";
        char[] charArray = str.toCharArray();
        List<String> strList = new ArrayList<>();
        for(int i=0; i< charArray.length; i++){
            String myChar = String.valueOf(charArray[i]);
            strList.add(myChar);
        }
        Map<String, Long> myMap =
                strList.stream().
                        collect(
                                Collectors.groupingBy(
                                        Function.identity(),Collectors.counting()
                                )
                        );
        myMap.forEach((k, v) -> {
            if (v == 1) {
                System.out.println(k);
            }
        });
    }
}

回答 2 件
  • 実際の頻度を計算するために、あなたはすでにほとんど最小限の例にいます!

    Map<Integer, Long> charFrequency = strList.stream() //Stream<String>
                .flatMapToInt(String::chars)  //Stream<IntStream> -> IntStream
                .boxed() //IntStream -> Stream<Integer>
                .collect(Collectors.groupingBy( //Map<K, V>
                        Function.identity(), //K == our integers
                        Collectors.counting() //V == the number of them
                ));
    charFrequency.entrySet().stream() //Stream<Map.Entry<Integer, Long>>
                .filter(ent -> ent.getValue() == 1) //only entries with value of 1
                .mapToInt(Map.Entry::getKey) //Stream<Entry> -> IntStream
                .forEach(c -> {
                    System.out.println("Found unique character: " + ((char) c));
                });
    
    

    そして、単一の文字列に対してそれを行うために、それはさらに簡単です(あなたは変換を保存します):

    Map<Integer, Long> charFrequency = someString.chars() //Stream<Integer>
                .collect(Collectors.groupingBy( //Map<K, V>
                        Function.identity(), //K == our integers
                        Collectors.counting() //V == the number of them
                ));
    
    

    そのために、私はあなたのコードが単に一貫性があり、読みやすいことを保証します。たとえば、一貫したインデントを使用して、ストリームが1行ごとにどのようにステップするかをコメントします。

    編集:OPの参考のために、以下の(古い)回答を残しましたが、実際の質問には回答していません。

    ええと、Stream#distinctは常にあります。

    「個別」の計算(ユニーク)文字:

    List<Integer> distinctChars = strList.stream() //Stream<String>
            .flatMapToInt(String::chars)  //Stream<IntStream> -> IntStream
            .distinct() //unique IntStream
            .boxed() //unique Stream<Integer>
            .collect(Collectors.toList()); //List<Integer>
    distinctChars.forEach(c -> {
        System.out.println("Found distinct char: " + ((char) (int) c));
    });
    
    

    あなたがそれを集めるのを避けたいならば、あなたはタイプボクシングの周りのすべての面倒を避けることもできます:

    strList.stream() //Stream<String>
            .flatMapToInt(String::chars)  //Stream<IntStream> -> IntStream
            .distinct() //unique IntStream
            .forEach(c -> {
                System.out.println("Found distinct char: " + ((char) c));
            });
    
    

  • ここにそれを行うための1つのかなりあいまいな方法があります。

    のストリームを作成します 0string length

    ここで、i + 1で始まる文字列に、iで始まる文字が含まれているかどうかを確認します。含まれている場合は、重複している必要があります。

    したがって、ストリームでインデックスを渡します。

    次に、そのインデックスを実際の文字にマップします。

    重複をすべて削除して、元の文字列のコピーを減らします。

    
    String str = "aabcddeffg";
    String result = IntStream.range(0,str.length())
    .filter(i->str.substring(i+1)
            .indexOf(str.charAt(i)) >= 0 )
    .mapToObj(i->str.substring(i,i+1)).reduce(str, (a,b)->a.replace(b,""));
    System.out.println(result);
    
    

    プリント

    bceg
    
    

あなたの答え