【问题标题】:How to combine two lists without using foreach?如何在不使用 foreach 的情况下合并两个列表?
【发布时间】:2018-06-21 20:27:11
【问题描述】:

原来我有这个代码:

String[] A;
String[] B;
//...
List<String> myList= new ArrayList<>(A.length + B.length);
for (int i= 0; i< B.length; i++){
   myList.add(A[i]);
   myList.add("*".equals(B[i]) ? B[i] : doSomethingWith(B[i]));
}

如果最好使用 Java 8,如何重构?

如果我有这些数组

A = {“一”、“二”、“三”、“四”}

B = {“五”、“六”、“七”、“八”}

在代码的最后,myList 将是:

myList = {“一”、“五”、“二”、“六”、“三”、“七”、“四”、“八”}

【问题讨论】:

  • 为什么不用foreach?
  • 我不会说这需要重构——它的作用已经很清楚了,尝试将它包装在某种流中可能只会让它更难理解。
  • @raullalves 顺便说一句,您现在没有使用实际的 foreach 循环
  • 也许使用两个迭代器而不是循环索引?但我真的不认为代码有问题。如果 SonarQube 抱怨,告诉它忽略它。

标签: java list collections


【解决方案1】:

我个人认为这不需要重构,因为任何“流式”代码都会比您现有的代码更不可读和更直观,但作为纯粹的概念证明:

String[] A;
String[] B;
List<String> myList;

myList = IntStream.range(0, B.length)
                  .mapToObj(i -> new String[]
                      {
                          A[i],
                          "*".equals(B[i]) ? B[i] : doSomethingWith(B[i])
                      })
                  .flatMap(Arrays::stream)
                  .collect(Collectors.toList());

Working demo.


  • 我们使用IntStream.range 将索引提供到我们的数组中。

  • mapToObj 将每个索引映射到包含我们想要的元素的数组(这个阶段也是需要的,因为IntStream::flatMap 只能转换为另一个IntStream,我们想将其转换为一个Stream Strings)。

  • flatMap 将每个数组映射到一个流,然后将结果流“展平”。

  • 最后,我们只是collect 结果。

【讨论】:

  • 确实,我个人看不出对所有事情都需要流/Java 8 解决方案的痴迷,因为它只会降低代码的可读性(在我看来)。
  • 这正是我想要的。非常感谢!
  • 你可以提高可读性 - 我有一点尝试,但它被拒绝了;然而,流媒体的好处超出了可读性。 OPs 解决方案必须进行“全数组扫描”,而流式解决方案可以延迟评估,可以跳过元素(并且计算,例如 doSomethingWith 不会发生在跳过的元素上),最后可以并行化,这在OP 情况下,会导致共享的、可能有争议的内存访问
  • @diginoise 我试图刻意模仿 OP 结构的某些部分——不过,我很欣赏Arrays::stream 的编辑。
  • new ArrayList&lt;&gt;(A.length + B.length)初始化myList是没有意义的;无论如何,它将被流操作的不相关结果覆盖。此外,您可以将其简化为 .mapToObj(i -&gt; Stream.of(A[i], "*".equals(B[i])? B[i]: doSomethingWith(B[i])) .flatMap(Function.identity())
【解决方案2】:

试试这样的:

 String[] A;
 String[] B;
 //...
 List<String> myList= Arrays.asList (A);
 List<String> myList2 = Arrays.stream(B).map(
    (x)->"*".equals(x) ? x : doSomethingWith(x))
    .collect(Collectors.toList());
 myList.addAll(myList2);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 1970-01-01
    • 2017-04-30
    相关资源
    最近更新 更多