programacion - ¿Hay una implementación básica del conjunto de Java que no permite valores nulos?
manual de programacion android pdf (14)
La API para la interfaz de Set Java establece:
Por ejemplo, algunas implementaciones prohíben elementos
null
y algunas tienen restricciones sobre los tipos de sus elementos
Estoy buscando una implementación de conjunto básico que no requiera ordenamiento (ya que ArrayList proporciona la interfaz de List ) y que no permite null
. TreeSet , HashSet y LinkedHashSet permiten elementos nulos. Además, TreeSet tiene el requisito de que los elementos implementen Comparable .
Parece que no existe tal Set
básico actualmente. ¿Alguien sabe por qué? ¿O si existe uno donde pueda encontrarlo?
[Editar]: no quiero permitir null
s, porque más adelante en el código mi clase iterará sobre todos los elementos en la colección y llamará a un método específico. (En realidad estoy usando HashSet<MyRandomObject
>). Prefiero fallar rápido que fracasar más tarde o incurrir accidentalmente en algún comportamiento extraño debido a un null
en el conjunto.
¿Por qué no quieres permitir null
?
¿Desea lanzar una excepción si null
se agrega a su conjunto? Si es así, solo haz algo como esto:
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
addAll()
HashSet
add()
repetidamente, por lo que este es el único método que debe sobrescribir.
En esta pregunta / ejemplo en particular, seguramente si tienes un HashSet<MyRandomObject> mySet
llama a mySet.remove(null)
antes de comenzar la iteración sobre todos los elementos que mencionaste.
Es mejor que extender una implementación particular, puede escribir fácilmente una implementación proxy de Set
que comprueba null
s. Esto es análogo a Collections.checkedSet
. Además de ser aplicable a cualquier implementación, también puede estar seguro de que ha anulado todos los métodos aplicables. Se han encontrado muchos defectos al extender colecciones de concreto que luego tienen métodos adicionales agregados en versiones posteriores.
Esta es una manera de lograrlo de manera general, ya que proporciona una implementación de filtro que puede restringir lo que se agrega de la manera que desee. Eche un vistazo a la fuente de java.util.Collections para obtener ideas sobre el ajuste (creo que mi implementación de la clase FilteredCollection es correcta ... pero no está ampliamente probada). Hay un programa de muestra al final que muestra el uso.
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);
}
}
Hashtable no permite valores nulos ...
No estoy seguro de un tipo que esto sea cierto. Pero, ¿no podría heredar de una colección o HashTable de su elección y anular el método Add, lanzando una excepción si el elemento es nulo?
No existe una implementación de conjunto de propiedad básica que ignore o restrinja el nulo. Hay EnumSet , pero ese es sastres para la contención de tipos enum.
Sin embargo, puede evitar la creación de su propia implementación, si usa Guava o Commons Collections :
1. Solución de guayaba:
Set noNulls = Constraints.constrainedSet(new HashSet(), Constraints.notNull());
2. Colecciones de Commons:
Set noNulls = new HashSet();
CollectionUtils.addIgnoreNull(noNulls, object);
Podrías escribir fácilmente el tuyo propio, subclasificando una clase existente apropiada y reemplazando todos los métodos relevantes para que no puedas agregar elementos null
.
Por cierto, si hubiera pedido una implementación de Map
que no permita nulos, la antigua java.util.Hashtable
no.
Puede usar las colecciones apache y su clase PredicatedCollection , y establecer el predicado para no permitir nulos. Obtendrá excepciones si alguien envía nulos.
También es posible que desees consultar Google Collections . Son más nulos fóbicos, creo.
Yo diría que usar composición en lugar de herencia ... podría ser más trabajo, pero será más estable frente a cualquier cambio que Sun pueda hacer en el Marco de Colecciones.
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 ...
}
Editar: También tenga en cuenta que esta implementación no depende de addAll calling add (que es un detalle de implementación y no debe utilizarse porque no se puede garantizar que siga siendo así en todas las versiones de Java).
Editar: se agregó un mensaje de error más descriptivo.
Editar: lo hizo tan claro () no devuelve nada.
Editar: lo hizo para que sea add (E e).
Editar: lanza IllegalArgumentException en lugar de NullPointerException.
para mí, no encontré uno, así que overrode the add function
Collection<String> errors = new HashSet<String>() {
@Override
public boolean add(String s) {
return StringUtil.hasContent(s) && super.add(s);//we don''t want add null and we allow HashSet.add(null)
}
};
Yes , en los documentos para com.google.common.collect.ImmutableSet
:
Un conjunto inmutable de alto rendimiento con un orden de iteración confiable y especificado por el usuario. No permite elementos nulos.