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

     2023-02-25     295

关键词:

【中文标题】有没有一种优雅的方法可以在使用 Guava 转换集合时删除空值?【英文标题】:Is there an elegant way to remove nulls while transforming a Collection using Guava? 【发布时间】:2010-12-20 15:10:16 【问题描述】:

我有一个关于在使用 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();
    
));

现在,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 代码(根本没有花哨的 Predicate 或 Function 的东西)可以说会更干净:

Collection<String> resourceIds = Lists.newArrayList();
for (Computer computer : matchingComputers) 
    String resourceId = computer.getResourceId();
    if (resourceId != null) 
        resourceIds.add(resourceId);
    

使用上述方法当然也是一种选择,但出于好奇(以及想了解更多 Google 收藏集),您能否使用 Google 收藏集以更短或更优雅的方式做同样的事情?

【问题讨论】:

【参考方案1】:

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() 方法将元素倒入任意集合中。

【讨论】:

【参考方案2】:

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 = ...;

这会更加干净(并且会促进重用)。

【讨论】:

很好的建议,谢谢!使用 Predicates.notNull() 并将函数放在一个常量中确实使代码更加清晰。 太棒了:)。当我使用函数作为转换时,我喜欢将它隔离在一个静态方法中并将其命名为 intoXXX(),我觉得它很容易阅读。在这种情况下,它可能是:transform(matchingCompters, intoResourceId()).【参考方案3】:

它比@Jon Skeet expected 花费了更长的时间,但 Java 8 流确实让这变得简单:

List<String> resourceIds = computers.stream()
    .map(Computer::getResourceId)
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

如果你愿意,也可以使用.filter(x -&gt; x != null); the difference is very minor.

【讨论】:

我正在寻找与 guava 的 Predicates#notNull() 等效的 Java8。没想到看Objects 这里是 API 文档:docs.oracle.com/javase/8/docs/api/java/util/…【参考方案4】:

您可以像这样编写自己的方法。这将为从 apply 方法返回 null 的任何函数过滤掉 null。

   public static <F, T> Collection<T> transformAndFilterNulls(List<F> fromList, Function<? super F, ? extends T> function) 
        return Collections2.filter(Lists.transform(fromList, function), Predicates.<T>notNull());
    

然后可以使用以下代码调用该方法。

Collection c = transformAndFilterNulls(Lists.newArrayList("", "SD", "DDF"), new Function<String, Long>() 

    @Override
    public Long apply(String s) 
        return s.isEmpty() ? 20L : null;
    
);
System.err.println(c);

【讨论】:

【参考方案5】:

首先,我会在某处创建一个常量过滤器:

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 中通过闭包和扩展方法变得更好 很多 :)

【讨论】:

我个人称它为 NOT_NULL_FILTER。 :) Predicates 类中已经有一个静态方法(见我的回答)。 @Cowan:这取决于您如何对待“过滤器”——您可能会争辩说它会过滤 空值。这是命名方面的普遍痛苦。但是,我认为它会做什么很明显,因为反过来会很愚蠢:) 不过对 Predicates 方法的调用很好。

转换集设置在java中

有没有一种简单的方法可以将Set<Integer>转换为Set<String>而无需遍历整个集合?答案不需要。您必须格式化每个整数并将其添加到字符串集中。另一答案Java7+Guava(可能无法切换到Java8)。newHashSet<>(Collections2.transform(<... 查看详情

有没有一种优雅的方法可以用 XSLT 添加多个 HTML 类?

】有没有一种优雅的方法可以用XSLT添加多个HTML类?【英文标题】:IsthereanelegantwaytoaddmultipleHTMLclasseswithXSLT?【发布时间】:2010-12-1004:18:23【问题描述】:假设我正在将多项选择测验从任意XML格式转换为HTML。每个选择都将在结果... 查看详情

有没有一种优雅的方法可以在 PyQt 中删除 QScrollArea 中的小部件?

】有没有一种优雅的方法可以在PyQt中删除QScrollArea中的小部件?【英文标题】:IsthereanelegantwaytodeleteawidgetinQScrollAreainPyQt?【发布时间】:2020-11-2309:34:03【问题描述】:我最近在学习PyQt5,当我想删除QScrollArea中的小部件时遇到问... 查看详情

guava学习笔记:optional优雅的使用null

...们才能更加深入体会领悟到Guava的Optional设计和使用上的优雅和简单。   null代表不确定的对象:  Java中,null是一个关键字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型... 查看详情

是否有一种优雅的方法可以在 SQL 插入语句中反转位值?

】是否有一种优雅的方法可以在SQL插入语句中反转位值?【英文标题】:IsthereanelegantwaytoInvertaBitvalueinanSQLinsertStatement?【发布时间】:2011-03-2011:32:15【问题描述】:我正在SQLServer中转换一些数据:INSERTINTOMYTABLE(AllowEdit)(SelectPreventE... 查看详情

如何使用guava的缓存管理

参考技术A  对于缓存首先需要明确的是:有没有一个方法可以通过给定的键来计算/加载相应的值?如果有,那么可以使用CacheLoader。如果没有这样的方法,或者你想复写缓存的加载方式,但你仍想保留“get-if-absent-compute”语... 查看详情

有没有一种优雅的方法来告诉 eslint 以确保我们没有使用任何 ES6 语法/函数?

】有没有一种优雅的方法来告诉eslint以确保我们没有使用任何ES6语法/函数?【英文标题】:Isthereanelegantwaytotelleslinttoensurethatwe\'renotusinganyES6syntax/functions?【发布时间】:2016-08-2901:55:31【问题描述】:有没有一种优雅的方式来告诉... 查看详情

有没有一种方法可以使用 Detox E2E 测试在 FlatList 中找到一个元素

】有没有一种方法可以使用DetoxE2E测试在FlatList中找到一个元素【英文标题】:IsthereawayIcanfindanelementinaFlatListusingDetoxE2Etesting【发布时间】:2021-07-1623:39:38【问题描述】:所以在测试我的应用程序时,我使用了一个数据集。由于数... 查看详情

有没有更优雅的方法来添加可为空的整数?

】有没有更优雅的方法来添加可为空的整数?【英文标题】:Isthereamoreelegantwaytoaddnullableints?【发布时间】:2011-04-0516:36:54【问题描述】:我需要添加大量可为null的int类型的变量。我使用空合并运算符将其降低为每行一个变量,... 查看详情

有没有一种简单的方法可以在 Oracle 8 上转换句子案例中的字符串?还是我应该使用正则表达式?

】有没有一种简单的方法可以在Oracle8上转换句子案例中的字符串?还是我应该使用正则表达式?【英文标题】:IsthereaeasywaytoconvertstringsinaSentenceCaseonOracle8?OrshouldIuseregex?【发布时间】:2015-12-2921:52:24【问题描述】:我知道在Oracle... 查看详情

有没有一种方法可以在没有单热编码的情况下使用具有分类变量的决策树?

】有没有一种方法可以在没有单热编码的情况下使用具有分类变量的决策树?【英文标题】:Isthereawaytousedecisiontreeswithcategoricalvariableswithoutone-hotencoding?【发布时间】:2019-11-1608:11:28【问题描述】:我有一个包含200多个分类变量... 查看详情

是否有一种优雅的内置方法可以在 R 中进行模索引?

】是否有一种优雅的内置方法可以在R中进行模索引?【英文标题】:Isthereanelegant,built-inwaytodomoduloindexinginR?【发布时间】:2018-04-0812:16:14【问题描述】:目前,我有extract_modulo=function(x,n,fn=`[`)fn(x,(n-1L)%%length(x)+1L)`%[mod%`=function(x,n)e... 查看详情

有没有一种方法可以用决策树/随机森林进行迁移学习?

】有没有一种方法可以用决策树/随机森林进行迁移学习?【英文标题】:Isthereamethodtodotransferlearningwithdecisiontrees/randomforest?【发布时间】:2021-08-0113:47:33【问题描述】:有没有办法使用决策树或随机森林模型进行迁移学习?具体... 查看详情

如何在 Java 中将 Integer[] 转换为 int[] 数组?

...t[]arrayinJava?【发布时间】:2015-10-0209:17:34【问题描述】:有没有一种奇特的方法可以将Integer数组转换为int数组?(我不想遍历每个元素;我正在寻找一种优雅而快速的方式来编写它)我正在使用另一种方式scaleTests.add(Arrays.stream(... 查看详情

一种将当前日期时间转换为 ISO 8601 格式的优雅方法 [重复]

】一种将当前日期时间转换为ISO8601格式的优雅方法[重复]【英文标题】:anelegantwaytotransfercurrentdatetimeintoISO8601format[duplicate]【发布时间】:2014-10-2519:04:06【问题描述】:我需要将当前日期时间转换为ios8601格式,例如:日期和时间... 查看详情

有没有一种简单的方法可以在 JavaScript 中将文本转换为 HTML? [复制]

】有没有一种简单的方法可以在JavaScript中将文本转换为HTML?[复制]【英文标题】:IsthereaneasywaytoconverttextintoHTMLinJavaScript?[duplicate]【发布时间】:2012-04-3007:15:13【问题描述】:可能重复:EscapingHTMLstringswithjQueryJavaScript/jQueryHTMLEncod... 查看详情

如何将图表转换为 HTML 折线

...ttoHTMLPolyline【发布时间】:2021-11-1112:13:12【问题描述】:有没有一种简单的方法可以将图表数据集转换为html折线图像。我在网上查了,但我找不到任何信息。像https://www.coingecko.com/en这样的网站在加载图像而不是整个数据集时使... 查看详情

在 PL/SQL 中将按表的索引转换为简单表的一种优雅方法,然后循环遍历每个条目

】在PL/SQL中将按表的索引转换为简单表的一种优雅方法,然后循环遍历每个条目【英文标题】:AnelegantwaytotransformanindexbytableintosimpletableinPL/SQL,otherthenloopthrougheveryentry【发布时间】:2011-06-0615:04:35【问题描述】:我有两种类型CREAT... 查看详情