Jon*_*nik 59 java collections refactoring guava
在使用Google Collections(更新:Guava)时,我有一个关于简化某些Collection处理代码的问题.
我有一堆"计算机"对象,我想最终收集他们的"资源ID".这样做是这样的:
Collection<Computer> matchingComputers = findComputers();
Collection<String> resourceIds = 
    Lists.newArrayList(Iterables.transform(matchingComputers, new Function<Computer, String>() {
    public String apply(Computer from) {
        return from.getResourceId();
    }
}));
现在,getResourceId()可能会返回null(并且现在更改它不是一个选项),但在这种情况下,我想从结果String集合中省略null.
这是过滤掉空值的一种方法:
Collections2.filter(resourceIds, new Predicate<String>() {
    @Override
    public boolean apply(String input) {
        return input != null;
    }
});
你可以像这样把所有这些放在一起:
Collection<String> resourceIds = Collections2.filter(
Lists.newArrayList(Iterables.transform(matchingComputers, new Function<Computer, String>() {
    public String apply(Computer from) {
        return from.getResourceId();
    }
})), new Predicate<String>() {
    @Override
    public boolean apply(String input) {
        return input != null;
    }
});
但对于这么简单的任务来说,这并不优雅,更不用说可读了!事实上,简单的旧Java代码(根本没有花哨的谓词或函数)可以说更清晰:
Collection<String> resourceIds = Lists.newArrayList();
for (Computer computer : matchingComputers) {
    String resourceId = computer.getResourceId();
    if (resourceId != null) {
        resourceIds.add(resourceId);
    }
}
使用上述内容当然也是一种选择,但出于好奇(并希望了解更多Google集合),您能否使用Google Collections以更短或更优雅的方式完成同样的事情?
Cow*_*wan 80
已经有一个谓词Predicates可以帮助你 - Predicates.notNull()- 你可以使用Iterables.filter()和事实,Lists.newArrayList()可以采取Iterable一点来清理这一点.
Collection<String> resourceIds = Lists.newArrayList(
  Iterables.filter(
     Iterables.transform(matchingComputers, yourFunction),
     Predicates.notNull()
  )
);
如果你实际上并不需要一个Collection,只需一个Iterable,那么这个Lists.newArrayList()电话也可以消失,你又一次走了一步!
我怀疑你可能会发现它Function会再次派上用场,并且最有用的声明为
public class Computer {
    // ...
    public static Function<Computer, String> TO_ID = ...;
}
它可以进一步清理它(并将促进重用).
Nat*_*tix 35
FluentIterable(自Guava 12以来)有点"更漂亮"的语法:
ImmutableList<String> resourceIds = FluentIterable.from(matchingComputers)
    .transform(getResourceId)
    .filter(Predicates.notNull())
    .toList();
static final Function<Computer, String> getResourceId =
    new Function<Computer, String>() {
        @Override
        public String apply(Computer computer) {
            return computer.getResourceId();
        }
    };
请注意,返回的列表是一个ImmutableList.但是,您可以使用copyInto()方法将元素倒入任意集合中.
Jef*_*oom 14
它花费的时间比@Jon Skeet预期的要长,但Java 8流确实使这个变得简单:
List<String> resourceIds = computers.stream()
    .map(Computer::getResourceId)
    .filter(Objects::nonNull)
    .collect(Collectors.toList());
.filter(x -> x != null)如果你愿意,你也可以使用; 差别很小.
首先,我在某处创建一个常量过滤器:
public static final Predicate<Object> NULL_FILTER =  new Predicate<Object>() {
    @Override
    public boolean apply(Object input) {
            return input != null;
    }
}
然后你可以使用:
Iterable<String> ids = Iterables.transform(matchingComputers,
    new Function<Computer, String>() {
        public String apply(Computer from) {
             return from.getResourceId();
        }
    }));
Collection<String> resourceIds = Lists.newArrayList(
    Iterables.filter(ids, NULL_FILTER));
您可以在代码中的任何位置使用相同的空过滤器.
如果你在其他地方使用相同的计算功能,你也可以使它成为常数,只留下:
Collection<String> resourceIds = Lists.newArrayList(
    Iterables.filter(
        Iterables.transform(matchingComputers, RESOURCE_ID_PROJECTION),
        NULL_FILTER));
这当然不是像你一样的C#相当于会,但是这一切都将得到大量的 Java 7中更好的与封闭和扩展方法:)