【问题标题】:Convert a for loop to concat String into a lambda expression将 for 循环转换为 concat String 为 lambda 表达式
【发布时间】:2015-10-06 01:23:08
【问题描述】:

我有以下 for 循环,它遍历字符串列表并将每个单词的第一个字符存储在 StringBuilder 中。我想知道如何将其转换为 lambda 表达式

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

【问题讨论】:

    标签: java collections lambda java-8 java-stream


    【解决方案1】:

    假设您之后在StringBuilder 上调用toString(),我认为您只是在将每个字符串映射到单个字符的子字符串之后寻找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,所以我们仍然可以使用字符串流。

    【讨论】:

      【解决方案2】:

      有很多方法可以做到这一点 - 最简单的选择:坚持添加到 StringBuilder 并这样做:

      StringBuilder chars = new StringBuilder();
      
      list.forEach(l -> chars.append(l.charAt(0)));
      

      【讨论】:

      • 那么你可以只使用list.forEach(…)而不使用.stream()
      【解决方案3】:

      无需创建许多中间 String 对象,您可以这样做:

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

      请注意,使用codePointAtcharAt 好得多,就好像您的字符串以代理对开头一样,使用charAt 您可能会得到不可预知的结果。

      【讨论】:

        【解决方案4】:

        这里有三种不同的解决方案来解决这个问题。每个解决方案首先过滤空字符串,否则可能会抛出 StringIndexOutOfBoundsException

        此解决方案与 Tagir 的解决方案相同,但添加了用于过滤空字符串的代码。我把它放在这里主要是为了与我提供的其他两种解决方案进行比较。

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

        第二个解决方案使用Eclipse Collections,并利用了一个相对较新的容器类型CodePointAdapter,它是在7.0 版中添加的。

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

        第三个解决方案再次使用 Eclipse Collections,但使用 injectIntoStringBuilder 而不是 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 的提交者。

        【讨论】:

          【解决方案5】:

          使用方法参考的简单方法:

          List<String> list = Arrays.asList("ABC", "CDE");
          StringBuilder sb = new StringBuilder();
          
          list.forEach(sb::append);
          
          String concatString = sb.toString();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-10-07
            • 1970-01-01
            • 1970-01-01
            • 2017-04-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多