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

时间:2015-08-24 16:57:12

标签: 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());        
}

但更整洁有效。

或者是否存在我不知道的内置方法?

3 个答案:

答案 0 :(得分:3)

我和其他人一样喜欢单行,但是他们付出了代价 - 也就是说,他们比阅读更难以阅读。所以让我们从“正常”的方式开始,做你正在描述的事情:

ArrayList<E> copy = new ArrayList<>(list);
copy.add(value);
return copy;

它有几行,但它高效,直接且易于阅读。我们希望任何替代方案都可以对此语法进行改进,而不是简单地替换可读性以实现简洁性。如果你试图在你发布的实现和“正常”版本之间做出决定,那么“正常”版本应该会胜出。

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

return Stream.concat(list.stream(), Stream.of(value))
    .collect(Collectors.toList());

技术上现在只有一个声明,但我们仍然需要将它分成多行以使其可读。它也比标准实现更多样板。

相反,我们可以使用构建器模式Guava为其Immutable collections提供:

return new ImmutableList.Builder<E>().addAll(list).add(value).build();

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

(很难读懂:))你的例子实际上用你的新值替换列表的最后一个值,而不是将它添加到最后。如果这是您想要的,只需使用List.sublist()截断列表中的最后一个元素,例如:

list.sublist(0, list.size() - 1)

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

答案 1 :(得分:1)

一个选项是使用

List<Integer> newList = (List<Integer>)ListUtils.union(list1,Arrays.asList(5));

来自Apache Commons Collections。我知道在内部这不是一个单一的陈述,而是那个有用的图书馆,很多人都有可能拥有它。

实施例

// Your list
ArrayList<Integer> myList = new ArrayList<Integer>();
myList.add(2);

// Create new list with new element
List<Integer> newList = (List<Integer>)ListUtils.union(myList,Arrays.asList(5));

答案 2 :(得分:0)

你可以试试这个

 private List<Integer> conjoin(List<Integer> list, final Integer newValue){
      ArrayList<Integer> returnlist = new ArrayList<Integer>(list) {{
            add(newValue);
        }};
    return returnlist;
    }