Is there a widely used util/library method in Java to tell if all elements in a collection are unique?

huangapple go评论51阅读模式
英文:

Is there a widely used util/library method in Java to tell if all elements in a collection are unique?

问题

I'm looking for a method that, if it were in the standard library, would probably be something like boolean Collections#areAllUnique(Collection). 我正在寻找一种方法,如果它在标准库中,可能会类似于 boolean Collections#areAllUnique(Collection)

I want a method that returns true iff there are no duplicates in the collection. 我想要一个方法,当集合中没有重复项时返回 true。

Obviously, this would return true for any (properly implemented) Set. 显然,对于任何(正确实现的)Set,这将返回 true。

It's also easy to write yourself, as something like collection.size() == new HashSet(collection).size(). However, there are a few reasons I'd still like to see it as a one-line library method: 你也可以很容易地自己编写,类似于 collection.size() == new HashSet(collection).size()。然而,还有一些原因,我仍然希望将其作为一行库方法:

  1. It's easier Is there a widely used util/library method in Java to tell if all elements in a collection are unique? 1)这更容易 Is there a widely used util/library method in Java to tell if all elements in a collection are unique?

  2. The above is not as efficient as it could be; the method could avoid building the entire second set if it detects any duplicates. 2)上述方法不如可能的效率高;如果检测到任何重复项,该方法可以避免构建整个第二个集合。

A good implementation might look like 一个良好的实现可能如下所示:

public static <T> boolean areAllUnique(Collection<T> collection) {
  if (collection instanceof Set) {
    return true;
  }
  HashSet<T> set = new HashSet<>(collection.size());
  for (T t : collection) {
    if (set.contains(t)) {
      return false;
    }
    set.add(t);
  }
  return true;
}

Is there a method like this somewhere in the Java standard library or any of the well-known libraries out there (Guava, etc.)? 在Java标准库或其他知名库中是否有类似这样的方法(例如Guava等)?

英文:

I'm looking for a method that, if it were in the standard library, would probably be something like boolean Collections#areAllUnique(Collection). I want a method that returns true iff there are no duplicates in the collection.

Obviously, this would return true for any (properly implemented) Set.

It's also easy to write yourself, as something like collection.size() == new HashSet(collection).size(). However, there are a few reasons I'd still like to see it as a one-line library method:

  1. It's easier Is there a widely used util/library method in Java to tell if all elements in a collection are unique?
  2. The above is not as efficient as it could be; the method could avoid building the entire second set if it detects any duplicates.

A good implementation might look like

public static &lt;T&gt; boolean areAllUnique(Collection&lt;T&gt; collection) {
  if (collection instanceof Set) {
    return true;
  }
  HashSet&lt;T&gt; set = new HashSet&lt;&gt;(collection.size());
  for (T t : collection) {
    if (set.contains(t)) {
      return false;
    }
    set.add(t);
  }
  return true;
}

Is there a method like this somewhere in the Java standard library or any of the well-known libraries out there (Guava, etc.)?

答案1

得分: 2

我相当确信Guava中不存在这样的方法。

您的方法基本上是正确的;我会对其进行一些微调,以使其稍微更清晰/更高效:

// T并不真正起作用。通配符就足够了。
public static boolean areAllUnique(Collection<?> collection) {
  if (collection instanceof Set) {
    return true;
  }
  HashSet<Object> set = new HashSet<>(collection.size());
  for (Object t : collection) {
    // add只在集合发生变化时返回true,因此您不需要分开进行contains/add操作。
    if (!set.add(t)) {
      return false;
    }
  }
  return true;
}

如果您想让API设计者感到沮丧(因为谓词应该是无状态的),您还可以更简洁地执行相同的操作:

return collection instanceof Set
    || collection.stream().allMatch(new HashSet<>(collection.size())::add);
英文:

I'm pretty sure that no such method exists in Guava.

Your method is mostly fine; I would make a couple of tweaks to it to make it marginally cleaner/more efficient:

// T doesn&#39;t really do anything. A wildcard is sufficient.
public static boolean areAllUnique(Collection&lt;?&gt; collection) {
  if (collection instanceof Set) {
    return true;
  }
  HashSet&lt;Object&gt; set = new HashSet&lt;&gt;(collection.size());
  for (Object t : collection) {
    // add only returns true if the set is changed, so you don&#39;t need to
    // do contains/add separately.
    if (!set.add(t)) {
      return false;
    }
  }
  return true;
}

If you want to make the API designers cry (because predicates should be stateless), you can also do the same thing more concisely:

return collection instanceof Set
    || collection.stream().allMatch(new HashSet&lt;&gt;(collection.size())::add);

huangapple
  • 本文由 发表于 2020年7月30日 18:23:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63171153.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定