有没有一种优雅的方法可以在使用番石榴转换集合时删除空值?

2022-08-31 16:34:28

我有一个关于在使用Google Collections时简化一些Collection处理代码的问题(更新Guava)。

我有一堆“计算机”对象,我想最终得到他们的“资源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();
    }
}));

现在,可能会返回null(现在更改它不是一个选项),但是在这种情况下,我想从生成的String集合中省略null。getResourceId()

以下是过滤掉空值的一种方法:

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 Collections),您可以使用Google Collections以更短或更优雅的方式做同样的事情吗


答案 1

词中已经有一个谓词可以帮助您,-- --您可以使用,并且可以使用的事实来进一步清理它。Predicates.notNull()Iterables.filter()Lists.newArrayList()Iterable

Collection<String> resourceIds = Lists.newArrayList(
  Iterables.filter(
     Iterables.transform(matchingComputers, yourFunction),
     Predicates.notNull()
  )
);

如果您实际上并不需要一个,只需一个,那么呼叫也可以消失,您又可以更干净了一步!CollectionIterableLists.newArrayList()

我怀疑你可能会发现,这将再次派上用场,并将最有用的声明为Function

public class Computer {
    // ...
    public static Function<Computer, String> TO_ID = ...;
}

这将进一步清理它(并将促进重用)。


答案 2

使用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();
        }
    };

请注意,返回的列表是一个 .但是,您可以使用方法将元素倒入任意集合中。ImmutableListcopyInto()