java - remove - ¿Cómo inicializar los valores de HashSet por construcción?




set hashset (15)

Usando Java 10 (Conjuntos no modificables)

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toUnmodifiableSet());

En este caso, el recopilador devolvería el conjunto no modificable introducido en Java 9 como se desprende del set -> (Set<T>)Set.of(set.toArray()) instrucciones set -> (Set<T>)Set.of(set.toArray()) en el código fuente.

Usando Java 9 (Conjuntos no modificables)

Set<String> strSet6 = Set.of("Apple", "Ball", "Cat", "Dog");

Usando Java 8 (Conjuntos modificables)

Usando Stream en Java 8.

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toCollection(HashSet::new));

// stream from an array (String[] stringArray)
Set<String> strSet2 = Arrays.stream(stringArray)
         .collect(Collectors.toCollection(HashSet::new));

// stream from a list (List<String> stringList)
Set<String> strSet3 = stringList.stream()
         .collect(Collectors.toCollection(HashSet::new));

Usando Java 8 (Conjuntos no modificables)

Usando Collections.unmodifiableSet - Podemos usar Collections.unmodifiableSet como:

Set<String> strSet4 = Collections.unmodifiableSet(strSet1);

Pero parece un poco incómodo y podemos escribir nuestro propio coleccionista así:

class ImmutableCollector {
    public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() {
        return Collector.of(HashSet::new, Set::add, (l, r) -> {
            l.addAll(r);
            return l;
        }, Collections::unmodifiablSet);
    }
}

Y luego usarlo como:

Set<String> strSet4 = Stream.of("A", "B", "C", "D")
             .collect(ImmutableCollector.toImmutableSet());

Usando Collectors.collectingAndThen - Otro enfoque es usar el método Collectors.collectingAndThen que nos permite realizar transformaciones de acabado adicionales:

import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
   toCollection(HashSet::new),Collections::unmodifiableSet));

Si solo nos preocupamos por Set , también podemos usar Collectors.toSet() en lugar de Collectors.toCollection(HashSet::new) .

Un punto a tener en cuenta es que el método Collections::unmodifiableSet devuelve una vista no modificable del conjunto especificado, según doc . Una colección de vista no modificable es una colección que no se puede modificar y también es una vista de una colección de respaldo. Tenga en cuenta que los cambios en la colección de respaldo podrían seguir siendo posibles, y si se producen, son visibles a través de la vista no modificable. Pero el método Collectors.unmodifiableSet devuelve un conjunto realmente inmutable en Java 10 .

https://code.i-harness.com

Necesito crear un Set con valores iniciales.

Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");

¿Hay una manera de hacer esto en una línea de código? Por ejemplo, es útil para un campo estático final.


(fea) Inicialización de doble refuerzo sin efectos secundarios:

Set<String> a = new HashSet<>(new HashSet<String>() {{
    add("1");
    add("2");
}})

Pero en algunos casos, si mencionamos que es un buen olor para hacer inmutables las colecciones finales, podría ser realmente útil:

final Set<String> a = Collections.unmodifiableSet(new HashSet<String>(){{
    add("1");
    add("2");
}})



En Java 8 yo usaría:

Set<String> set = Stream.of("a", "b").collect(Collectors.toSet());

Esto le da un Set mutable preinicializado con "a" y "b". Tenga en cuenta que mientras en JDK 8 esto devuelve un HashSet , la especificación no lo garantiza, y esto podría cambiar en el futuro. Si desea específicamente un HashSet , haga esto en su lugar:

Set<String> set = Stream.of("a", "b")
                        .collect(Collectors.toCollection(HashSet::new));

Esta es una solución elegante:

public static final <T> Set<T> makeSet(@SuppressWarnings("unchecked") T... o) {
        return new HashSet<T>() {
            private static final long serialVersionUID = -3634958843858172518L;
            {
                for (T x : o)
                   add(x);
            }
        };
}

Hay una taquigrafía que utilizo que no es muy eficiente en el tiempo, pero se ajusta a una sola línea:

Set<String> h = new HashSet<>(Arrays.asList("a", "b"));

Nuevamente, esto no es eficiente en el tiempo ya que está construyendo una matriz, convirtiéndose en una lista y utilizando esa lista para crear un conjunto.

Al inicializar conjuntos finales estáticos, normalmente lo escribo así:

public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));

Un poco menos feo y la eficiencia no importa para la inicialización estática.


Los literales de colección estaban programados para Java 7, pero no lo lograron. Así que todavía no hay nada automático.

Puedes usar los Sets de guayaba:

Sets.newHashSet("a", "b", "c")

O puede usar la siguiente sintaxis, que creará una clase anónima, pero es intrépida:

Set<String> h = new HashSet<String>() {{
    add("a");
    add("b");
}};

Puedes hacerlo en Java 6:

Set<String> h = new HashSet<String>(Arrays.asList("a", "b", "c"));

¿Pero por qué? No encuentro que sea más legible que agregar elementos explícitamente.


Si el tipo contenido del Conjunto es una enumeración, entonces hay un método de fábrica construido en Java (desde la versión 1.5):

Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... );

Siento que lo más legible es simplemente usar google Guava:

Set<String> StringSet = Sets.newSet("a", "b", "c");

Solo una pequeña nota, independientemente de cuál de los enfoques finos mencionados aquí termine, si esta es una opción predeterminada que generalmente no se modifica (como la configuración predeterminada en una biblioteca que está creando), es una buena idea seguir este patrón. :

// Initialize default values with the method you prefer, even in a static block
// It's a good idea to make sure these defaults aren't modifiable
private final static Set<String> DEFAULT_VALUES = Collections.unmodifiableSet(...);
private Set<String> values = DEFAULT_VALUES;

El beneficio depende de la cantidad de instancias que cree de esa clase y de la probabilidad de que se cambien los valores predeterminados.

Si decide seguir este patrón, también puede elegir el método de inicialización de conjuntos que sea más fácil de leer. Como las diferencias micro en la eficiencia entre los diferentes métodos probablemente no importarán mucho, ya que iniciará el conjunto solo una vez.


Una de las formas más convenientes es el uso del método genérico Collections.addAll() , que toma una colección y varargs:

Set<String> h = new HashSet<String>();
Collections.addAll(h, "a", "b");

Una generalización de la función de utilidad de respuesta de coobird para crear nuevos HashSet s:

public static <T> Set<T> newHashSet(T... objs) {
    Set<T> set = new HashSet<T>();
    for (T o : objs) {
        set.add(o);
    }
    return set;
}

import com.google.common.collect.Sets;
Sets.newHashSet("a", "b");

o

import com.google.common.collect.ImmutableSet;
ImmutableSet.of("a", "b");




hashset