使用Guava检查是否只存在一个元素

5

最近我需要在集合中只有一个元素的情况下执行“特殊情况”场景。检查...size() == 1并使用...iterator.next()进行检索看起来很丑,因此我在自制的 Collections 类中创建了两种方法:

public class Collections {
    public static <T> boolean isSingleValue(Collection<T> values) {
        return values.size() == 1;
    }

    public static <T> T singleValue(Collection<T> values) {
        Assert.isTrue(isSingleValue(values));
        return values.iterator().next();
    }
}

几天前,我发现Guava有一个叫做Iterables.getOnlyElement的方法。它满足了我的需求,替代了singleValue,但我找不到匹配isSingleValue的方法。这是设计上的吗?值得提出功能请求来添加Iterables.isOnlyElement方法吗? 编辑: 由于有一些赞同,我决定在Guava上开启增强功能 - issue 957。最终解决方案是“不修复”。论据与Thomas/Xaerxess提供的非常相似。
3个回答

10

嗯,通过替换values.size() == 1为一个方法你不会得到很多收益,除非你想检查null。然而,Apache Commons Collections(以及Guava,我猜)中有相应的方法来实现这一点。

我更喜欢写if( values.size() == 1 )或者 if( SomeHelper.size(values) == 1 )
而不是if( SomeHelper.isSingleValue(values) )——前两种方法意图更清晰,与第三种方法一样简洁。


6
除了其他答案之外(我本来想写类似于@daveb的东西,他删除了自己的一个:如果没有恰好一个元素,则Iterables#getOnlyElement会抛出IllegalArgumentExceptionNoSuchElementException) - 关于为什么Guava中没有任何Iterables.isSingleValue(Iterable)的答案。
我认为你错了。如果:
  • 方法调用不改变状态(与迭代器中的next()不同,这就是为什么存在hasNext()
  • 您可以明确而明确地说返回的值不是异常情况(与从Map#get(Object)返回的null不同 - 它可以是null值,也可以意味着在地图中找不到键)
那么就不需要检查条件是否为真,然后执行某些操作(其中包含断言!),就像您的示例代码中一样。
如果您绝对确定此处的可迭代对象除了大小为1以外不能有其他大小,则条件检查是冗余的(在其他情况下会引发异常)。
如果您只想在非空集合中获取第一个元素-collection.iterator.next()完全可以(如果集合为空,则抛出NoSuchElementException)。
如果您不知道集合的大小,则Iterables.getFirst(iterable, default)适合您。
附言:如果您的Collections#isSingleValue仅在此处本地使用(因此可以是私有的),则意味着在调用Iterables#getOnlyValue之前不需要进行检查。
另一个回答您关于Guava设计的问题可能是Joshua Bloch的《Effective Java》第57项 - Guava中有几种不同的助手方法,我之前提到过每个方法明确说明了什么是异常情况;没有添加布尔检查是因为尽可能保持API小。

0

我现在也遇到了同样的问题。

我将使用以下代码来解决:

public static <T> void hasJustOne(T... values) {
    hasJustOne(Predicates.notNull(), values);
}

public static <T> void hasJustOne(Predicate<T> predicate, T... values) {
    Collection<T> filtred = Collections2.filter(Arrays.asList(values),predicate);
    Preconditions.checkArgument(filtred.size() == 1);
}

这不太清楚,“I'll to solve”是什么意思?你是在说这是一个解决方案,还是你正在解决这个问题? - Adi Inbar
这对我来说是解决方案。 - Falci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接