流畅地添加到Collection(添加并返回值)

时间:2016-06-16 07:58:54

标签: java collections guava apache-commons

我一次又一次地发现自己处于想要使用值的情况,并将其同时添加到集合中,例如:

List<String> names = new ArrayList<>();
person1.setName(addTo(names, "Peter"));
person2.setName(addTo(names, "Karen"));

(注意:使用java.util.Collection.add(E)当然不起作用,因为它返回一个布尔值。)

当然,自己编写实用程序方法很容易:

public static <E> E addTo(Collection<? super E> coll, E elem) {
    coll.add(elem);
    return elem;
}

但JavaSE,Commons Collections,Guava还是其他一些“标准”库中是否真的没有这样的东西呢?

2 个答案:

答案 0 :(得分:2)

如果您使用Eclipse Collections

,以下内容将有效
MutableList<String> names = Lists.mutable.empty();
person1.setName(names.with("Peter").getLast());
person2.setName(names.with("Karen").getLast());

with方法返回要添加的集合,以便您可以根据需要轻松链接添加。在getLast(扩展with)上调用MutableList后使用java.util.List,即可获得刚刚添加的元素。

注意:我是Eclipse Collections的提交者。

答案 1 :(得分:1)

对我来说这看起来很奇怪。像person1.setName(addTo(names, "Peter"))这样的行似乎是倒置的,很难正确解析:

  

为现有人物对象分配名称,该名称将首先添加到名称列表中,名称为&#34;彼得&#34;。

与(例如)person1.setName("Peter"); names.add(person1.getName());对比:

  

制作&#34;彼得&#34;现有person对象的名称,然后将该名称添加到名称列表中。

我很欣赏它的两个陈述而不是一个陈述,但相对于你提出的不同寻常的语义而言,这是一个非常低的成本。后一种格式更容易理解,更容易重构,更具惯用性。

我愿意下注许多可能会从您的addTo()方法中获益的方案存在其他问题,并且可以通过之前的不同重构更好地服务。

其核心问题似乎是您尝试表示复杂数据类型(Person),同时构建一个由这些对象的特定方面组成的无关列表。一个可能更简单(并且仍然流畅)的选项是构造Person对象列表,然后转换该列表以提取所需的值。考虑:

List<Person> people = ImmutableList.of(new Person("Peter"), new Person("Karen"));
List<String> names = people.stream().map(Person::getName).collect(toList());

请注意,我们不再需要孤立的person1person2变量,现在peoplenames之间存在更直接的关系。根据您的需要names,您可以完全避免构建第二个列表,例如与List.forEach()

如果您还没有使用Java 8,那么您仍然可以使用Guava's functional utilities的函数语法。该页面上的警告也值得一读,即使在Java-8-land中也是如此。