如何创建新列表并在单个语句中添加值

Nab*_*ska 3 java lambda functional-programming

我想要实现的目标可能毫无意义,但我想找到答案来满足我的好奇心。

我正在尝试创建一个有效的语句,该语句将基于另一个列表创建一个新列表,并在末尾添加一个新值。

我是 lambda 表达式的新手,我不确定应该使用哪种列表。

该方法看起来像这样:

private List<Integer> conjoin(List<Integer> list, Integer newValue){
    return new ArrayList<Integer>(list).stream()
            .map(value -> list.indexOf(value)==(list.size()-1) ? 
                    Arrays.asList(value, newValue) : 
                    Arrays.asList(value))
            .flatMap(Collection::stream)
            .collect(Collectors.toList());        
}
Run Code Online (Sandbox Code Playgroud)

但更加整洁和高效。

或者是否有一个内置方法可以执行我不知道的相同操作?

dim*_*414 6

我和其他人一样喜欢俏皮话,但它们是有代价的——也就是说,它们比明确的内容更难读。因此,让我们从“正常”方式开始执行您所描述的操作:

ArrayList<E> copy = new ArrayList<>(list);
copy.add(value);
return copy;
Run Code Online (Sandbox Code Playgroud)

它只有几行,但高效、直接且易于阅读。我们希望任何替代方案都能改进这种语法,而不是为了简洁而简单地取代可读性。如果您试图在您发布的实现和“正常”版本之间做出决定,那么“正常”版本应该轻而易举地获胜。


我们可以尝试使用Stream.concat()和改进您的解决方案Stream.of()

return Stream.concat(list.stream(), Stream.of(value))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

从技术上讲,现在它只是一个语句,但我们仍然需要将其拆分为多行以使其可读。它的样板代码也比标准实现多得多。


相反,我们可以使用Guava为其不可变集合提供的构建器模式:

return new ImmutableList.Builder<E>().addAll(list).add(value).build();
Run Code Online (Sandbox Code Playgroud)

这更加简洁,并且很好地传达了我们的意图。这就是我建议实现您所描述的行为的方式(使用 Guava 或定义您自己的构建器模式)。它不仅适用于这个特定的用例,而且可以扩展到值和集合的任意组合。


认为(很难阅读:))您的示例实际上用新值替换了列表的最后一个值,而不是将其添加到末尾。如果这就是您想要的,只需用于List.sublist()截断列表中的最后一个元素,例如:

list.sublist(0, list.size() - 1)
Run Code Online (Sandbox Code Playgroud)

在上面的任何地方使用它list来排除最后一个值。