web-dev-qa-db-ja.com

forループを変換してStringをラムダ式に連結します

文字列のリストを反復処理し、各Wordの最初の文字をStringBuilderに格納する次のforループがあります。これをラムダ式に変換する方法を知りたい

StringBuilder chars = new StringBuilder();
for (String l : list) {
    chars.append(l.charAt(0));
}  
24
Faktor 10

後でStringBuildertoString()を呼び出すと仮定すると、各文字列を単一にマッピングした後、 Collectors.joining() を探しているだけだと思います-文字サブストリング:

String result = list
    .stream()
    .map(s -> s.substring(0, 1))
    .collect(Collectors.joining());

サンプルコード:

import Java.util.*;
import Java.util.stream.*;

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("foo");
        list.add("bar");
        list.add("baz");
        String result = list
            .stream()
            .map(s -> s.substring(0, 1))
            .collect(Collectors.joining());
        System.out.println(result); // fbb
    }
}

substringの代わりにcharAtを使用していることに注意してください。そのため、処理する文字列のストリームが残っています。

40
Jon Skeet

これを行うための多くの方法-最も単純なオプションStringBuilderへの追加に固執し、これを行います:

    final StringBuilder chars = new StringBuilder();

    list.forEach(l -> chars.append(l.charAt(0)));
18
Fritz Duchardt

多くの中間文字列オブジェクトを作成せずに、次のようにすることができます。

StringBuilder sb = list.stream()
                       .mapToInt(l -> l.codePointAt(0))
                       .collect(StringBuilder::new, 
                                StringBuilder::appendCodePoint, 
                                StringBuilder::append);

codePointAtを使用すると、文字列がサロゲートペアで始まるかのようにcharAtよりもはるかに優れていることに注意してください。charAtを使用すると、予測できない結果が生じる可能性があります。

13
Tagir Valeev

この問題に対する3つの異なる解決策を以下に示します。各ソリューションは、空の文字列を最初にフィルタリングします。そうしないと、StringIndexOutOfBoundsExceptionがスローされる場合があります。

このソリューションは、空の文字列をフィルタリングするためのコードが追加されたTagirのソリューションと同じです。主に、提供した他の2つのソリューションと比較するために、ここに含めました。

List<String> list =
    Arrays.asList("the", "", "quick", "", "brown", "", "fox");
StringBuilder builder = list.stream()
    .filter(s -> !s.isEmpty())
    .mapToInt(s -> s.codePointAt(0))
    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append);
String result = builder.toString();
Assert.assertEquals("tqbf", result);

2番目のソリューションは Eclipse Collections を使用し、バージョン7.0で追加された CodePointAdapter と呼ばれる比較的新しいコンテナータイプを活用します。

MutableList<String> list =
    Lists.mutable.with("the", "", "quick", "", "brown", "", "fox");
LazyIntIterable iterable = list.asLazy()
    .reject(String::isEmpty)
    .collectInt(s -> s.codePointAt(0));
String result = CodePointAdapter.from(iterable).toString();
Assert.assertEquals("tqbf", result);

3番目のソリューションでは、Eclipseコレクションを再び使用しますが、injectIntoの代わりに StringBuilder およびCodePointAdapterを使用します。

MutableList<String> list =
    Lists.mutable.with("the", "", "quick", "", "brown", "", "fox");
StringBuilder builder = list.asLazy()
    .reject(String::isEmpty)
    .collectInt(s -> s.codePointAt(0))
    .injectInto(new StringBuilder(), StringBuilder::appendCodePoint);
String result = builder.toString();
Assert.assertEquals("tqbf", result);

注:私はEclipse Collectionsのコミッターです。

3
Donald Raab

メソッド参照を使用した簡単な方法:

List<String> list = Arrays.asList("ABC", "CDE");
StringBuilder sb = new StringBuilder();

list.forEach(sb::append);

String concatString = sb.toString();
0
Rahul Chauhan