是否有不允许空值的基本 Java Set 实现?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/591115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a basic Java Set implementation that does not permit nulls?
提问by Aaron K
The API for the Java Setinterface states:
Java Set接口的 API说明:
For example, some implementations prohibit
null
elements and some have restrictions on the types of their elements
例如,有些实现禁止
null
元素,有些实现对其元素的类型有限制
I am looking for a basic Set implementation that does not require ordering (as ArrayListprovides for the Listinterface) and that does not permit null
. TreeSet, HashSet, and LinkedHashSetall allow null elements. Additionally, TreeSet has the requirement that elements implement Comparable.
我正在寻找一个基本的 Set 实现,它不需要排序(因为ArrayList为List接口提供)并且不允许null
. TreeSet、HashSet和LinkedHashSet都允许空元素。此外, TreeSet 要求元素实现Comparable。
It seems that no such basic Set
exists currently. Does anyone know why? Or if one does exist where I can find it?
目前似乎没有这样的基本Set
存在。有谁知道为什么?或者,如果确实存在我可以找到的地方?
[Edit]: I do not want to allow null
s, because later in the code my class will iterate over all elements in the collection and call a specific method. (I'm actually using HashSet<MyRandomObject
>). I would rather fail fast than fail later or accidentally incur some bizarre behavior due to a null
being in the set.
[编辑]:我不想允许null
s,因为稍后在代码中,我的类将遍历集合中的所有元素并调用特定方法。(我实际上正在使用HashSet<MyRandomObject
>)。我宁愿快速失败也不愿稍后失败,或者由于null
在系列中而意外引发一些奇怪的行为。
采纳答案by Tom Hawtin - tackline
Better than extending a particular implementation, you can easily write a proxy implementation of Set
that checks for null
s. This analogous to Collections.checkedSet
. Other than being applicable to any implementation, you can also be sure that you have overridden all applicable methods. Many flaws have been found by extending concrete collections which then have additional methods added in later versions.
比扩展特定实现更好,您可以轻松编写Set
检查null
s的代理实现。这类似于Collections.checkedSet
. 除了适用于任何实现之外,您还可以确保您已经覆盖了所有适用的方法。通过扩展具体集合发现了许多缺陷,然后在以后的版本中添加了额外的方法。
回答by mipadi
You could easily write your own, by subclassing an appropriate existing class, and overriding all relevant methods so that you can'tadd null
elements.
您可以轻松地编写自己的类,方法是将适当的现有类子类化,并覆盖所有相关方法,这样您就无法添加null
元素。
回答by REA_ANDREW
I am not sure of a type which this is true. But could you not inherit from a collection or HashTable of your choice and override the Add method, throwing an exception if the element is null?
我不确定这是真的类型。但是您不能从您选择的集合或 HashTable 继承并覆盖 Add 方法,如果元素为 null 则抛出异常吗?
回答by Michael Myers
Why do you not want to allow null
?
你为什么不想允许null
?
Do you want to throw an exception if null
is added to your set? If so, just do something like this:
如果null
添加到您的集合中,您想抛出异常吗?如果是这样,只需执行以下操作:
private Set<Object> mySet = new HashSet<Object>() {
@Override
public boolean add(Object e) {
if (e == null)
throw new IllegalArgumentException("null"); // or NPE
// or, of course, you could just return false
return super.add(e);
}
};
HashSet
's addAll()
calls add()
repeatedly, so this is the only method you'd have to override.
HashSet
的addAll()
调用add()
重复,所以这是您必须覆盖的唯一方法。
回答by cdmckay
I would say use composition instead of inheritance... it might be more work but it'll be more stable in the face of any changes that Sun might make to the Collections Framework.
我会说使用组合而不是继承......它可能需要更多的工作,但面对 Sun 可能对集合框架进行的任何更改,它会更加稳定。
public class NoNullSet<E> implements Set<E>
{
/** The set that is wrapped. */
final private Set<E> wrappedSet = new HashSet<E>();
public boolean add(E e)
{
if (e == null)
throw new IllegalArgumentException("You cannot add null to a NoNullSet");
return wrappedSet.add(e);
}
public boolean addAll(Collection<? extends E> c)
{
for (E e : c) add(e);
}
public void clear()
{ wrappedSet.clear(); }
public boolean contains(Object o)
{ return wrappedSet.contains(o); }
... wrap the rest of them ...
}
Note that this implementation does not depend on addAll
calling add
(which is an implementation detail and should not be used because it cannot be guaranteed to remain true in all Java releases).
请注意,此实现不依赖于addAll
调用add
(这是一个实现细节,不应使用,因为不能保证在所有 Java 版本中都保持正确)。
回答by Julien Chastang
You may also wish to check out Google Collections. They are more null phobic, I believe.
您可能还希望查看Google Collections。我相信,他们更怕空。
回答by Uri
You could use apache collections and its PredicatedCollection class, and set the predicate to not allow nulls. You will get exceptions if someone sends nulls in.
您可以使用 apache 集合及其PredicatedCollection 类,并将谓词设置为不允许空值。如果有人发送空值,您将收到异常。
回答by TofuBeer
This is a failry general purpose way of doing it - you provide a Filter implementation that can restrict what gets added in whatevber way you want. Take a look at the source for java.util.Collections for ideas on the wrapping (I think my implementaiton of the FilteredCollection class is correct... but it is not extensivly tested). There is a sample program at the end that shows the usage.
这是一种失败的通用方法 - 您提供了一个过滤器实现,可以限制以您想要的任何方式添加的内容。查看 java.util.Collections 的源代码以获取有关包装的想法(我认为我对 FilteredCollection 类的实现是正确的......但它没有经过广泛测试)。最后有一个示例程序显示了用法。
public interface Filter<T>
{
boolean accept(T item);
}
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
public class FilteredCollections
{
private FilteredCollections()
{
}
public static <T> Collection<T> filteredCollection(final Collection<T> c,
final Filter<T> filter)
{
return (new FilteredCollection<T>(c, filter));
}
private static class FilteredCollection<E>
implements Collection<E>,
Serializable
{
private final Collection<E> wrapped;
private final Filter<E> filter;
FilteredCollection(final Collection<E> collection, final Filter<E> f)
{
if(collection == null)
{
throw new IllegalArgumentException("collection cannot be null");
}
if(f == null)
{
throw new IllegalArgumentException("f cannot be null");
}
wrapped = collection;
filter = f;
}
public int size()
{
return (wrapped.size());
}
public boolean isEmpty()
{
return (wrapped.isEmpty());
}
public boolean contains(final Object o)
{
return (wrapped.contains(o));
}
public Iterator<E> iterator()
{
return new Iterator<E>()
{
final Iterator<? extends E> i = wrapped.iterator();
public boolean hasNext()
{
return (i.hasNext());
}
public E next()
{
return (i.next());
}
public void remove()
{
i.remove();
}
};
}
public Object[] toArray()
{
return (wrapped.toArray());
}
public <T> T[] toArray(final T[] a)
{
return (wrapped.toArray(a));
}
public boolean add(final E e)
{
final boolean ret;
if(filter.accept(e))
{
ret = wrapped.add(e);
}
else
{
// you could throw an exception instead if you want -
// IllegalArgumentException is what I would suggest
ret = false;
}
return (ret);
}
public boolean remove(final Object o)
{
return (wrapped.remove(o));
}
public boolean containsAll(final Collection<?> c)
{
return (wrapped.containsAll(c));
}
public boolean addAll(final Collection<? extends E> c)
{
final E[] a;
boolean result;
a = (E[])wrapped.toArray();
result = false;
for(final E e : a)
{
result |= wrapped.add(e);
}
return result;
}
public boolean removeAll(final Collection<?> c)
{
return (wrapped.removeAll(c));
}
public boolean retainAll(final Collection<?> c)
{
return (wrapped.retainAll(c));
}
public void clear()
{
wrapped.clear();
}
public String toString()
{
return (wrapped.toString());
}
}
}
import java.util.ArrayList;
import java.util.Collection;
public class Main
{
private static class NullFilter<T>
implements Filter<T>
{
public boolean accept(final T item)
{
return (item != null);
}
}
public static void main(final String[] argv)
{
final Collection<String> strings;
strings = FilteredCollections.filteredCollection(new ArrayList<String>(),
new NullFilter<String>());
strings.add("hello");
strings.add(null);
strings.add("world");
if(strings.size() != 2)
{
System.err.println("ERROR: strings.size() == " + strings.size());
}
System.out.println(strings);
}
}
回答by Michael Borgwardt
BTW, if you'd asked for a Map
implementation that does not allow nulls, the old java.util.Hashtable
does not.
顺便说一句,如果你要求一个Map
不允许空值的实现,旧的java.util.Hashtable
则不允许。
回答by Pavithra
Hashtable does not allow null values......
Hashtable 不允许空值......