remove objetos declarar coleccion clase java collections constructor initialization hashset

objetos - java hashset methods



¿Cómo inicializar los valores de HashSet por construcción? (22)

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 .

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"); }})


Con Eclipse Collections, hay varias maneras diferentes de inicializar un Set contiene los caracteres ''a'' y ''b'' en una declaración. Eclipse Collections tiene contenedores para objetos y tipos primitivos, así que CharSet cómo podría usar un Set<String> o CharSet además de las versiones mutables, inmutables, sincronizadas y no modificables de ambos.

Set<String> set = Sets.mutable.with("a", "b"); HashSet<String> hashSet = Sets.mutable.with("a", "b").asLazy().into(new HashSet<String>()); Set<String> synchronizedSet = Sets.mutable.with("a", "b").asSynchronized(); Set<String> unmodifiableSet = Sets.mutable.with("a", "b").asUnmodifiable(); MutableSet<String> mutableSet = Sets.mutable.with("a", "b"); MutableSet<String> synchronizedMutableSet = Sets.mutable.with("a", "b").asSynchronized(); MutableSet<String> unmodifiableMutableSet = Sets.mutable.with("a", "b").asUnmodifiable(); ImmutableSet<String> immutableSet = Sets.immutable.with("a", "b"); ImmutableSet<String> immutableSet2 = Sets.mutable.with("a", "b").toImmutable(); CharSet charSet = CharSets.mutable.with(''a'', ''b''); CharSet synchronizedCharSet = CharSets.mutable.with(''a'', ''b'').asSynchronized(); CharSet unmodifiableCharSet = CharSets.mutable.with(''a'', ''b'').asUnmodifiable(); MutableCharSet mutableCharSet = CharSets.mutable.with(''a'', ''b''); ImmutableCharSet immutableCharSet = CharSets.immutable.with(''a'', ''b''); ImmutableCharSet immutableCharSet2 = CharSets.mutable.with(''a'', ''b'').toImmutable();

Eclipse Collections es compatible con Java 5 - 8.

Nota: Soy un comendador de Eclipse Collections.




El patrón Builder podría ser de utilidad aquí. Hoy tuve el mismo problema. donde necesitaba Configurar operaciones de mutación para que me devolviera una referencia del objeto Conjunto, de modo que pueda pasarlo al constructor de súper clase para que también puedan continuar agregando al mismo conjunto construyendo un nuevo StringSetBuilder fuera del Conjunto que la clase secundaria acaba de construir. La clase de constructor que escribí se parece a esto (en mi caso es una clase interna estática de una clase externa, pero también puede ser su propia clase independiente):

public interface Builder<T> { T build(); } static class StringSetBuilder implements Builder<Set<String>> { private final Set<String> set = new HashSet<>(); StringSetBuilder add(String pStr) { set.add(pStr); return this; } StringSetBuilder addAll(Set<String> pSet) { set.addAll(pSet); return this; } @Override public Set<String> build() { return set; } }

Observe los métodos addAll() y add() , que son las contrapartes establecidas por Set.add() y Set.addAll() . Finalmente, observe el método build() , que devuelve una referencia al conjunto que encierra el constructor. A continuación se ilustra cómo usar este constructor de conjuntos:

class SomeChildClass extends ParentClass { public SomeChildClass(String pStr) { super(new StringSetBuilder().add(pStr).build()); } } class ParentClass { public ParentClass(Set<String> pSet) { super(new StringSetBuilder().addAll(pSet).add("my own str").build()); } }


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 algunas maneras:

Inicialización de doble refuerzo

Esta es una técnica que crea una clase interna anónima que tiene un inicializador de instancia que agrega String s a sí misma cuando se crea una instancia:

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

Tenga en cuenta que esto creará realmente una nueva subclase de HashSet cada vez que se use, aunque uno no tenga que escribir explícitamente una nueva subclase.

Un método de utilidad

Escribir un método que devuelva un Set que se inicializa con los elementos deseados no es demasiado difícil de escribir:

public static Set<String> newHashSet(String... strings) { HashSet<String> set = new HashSet<String>(); for (String s : strings) { set.add(s); } return set; }

El código anterior solo permite el uso de una String , pero no debería ser demasiado difícil permitir el uso de cualquier tipo usando genéricos.

Usa una biblioteca

Muchas bibliotecas tienen un método conveniente para inicializar objetos de colecciones.

Por ejemplo, Google Collections tiene un Sets.newHashSet(T...) que HashSet un HashSet con elementos de un tipo específico.


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"); }};


Puede usar bloque estático para la inicialización:

private static Set<Integer> codes1= new HashSet<Integer>(Arrays.asList(1, 2, 3, 4)); private static Set<Integer> codes2 = new HashSet<Integer>(Arrays.asList(5, 6, 7, 8)); private static Set<Integer> h = new HashSet<Integer>(); static{ h.add(codes1); h.add(codes2); }


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, ... );


Si solo tiene un valor inicial en conjunto, esto sería suficiente:

Set<String> h = Collections.singleton("a");


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.


Un poco complicado pero funciona desde Java 5:

Set<String> h = new HashSet<String>(Arrays.asList(new String[] { "a", "b" }))

Use un método auxiliar para hacerlo legible:

Set<String> h = asSet ("a", "b"); public Set<String> asSet(String... values) { return new HashSet<String>(java.util.Arrays.asList(values)); }


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; }


Usando Java 8 podemos crear HashSet como:

Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new));

Y si queremos un conjunto no modificable podemos crear un método de utilidad como:

public static <T, A extends Set<T>> Collector<T, A, Set<T>> toImmutableSet(Supplier<A> supplier) { return Collector.of( supplier, Set::add, (left, right) -> { left.addAll(right); return left; }, Collections::unmodifiableSet); }

Este método puede ser utilizado como:

Stream.of("A", "B", "C", "D").collect(toImmutableSet(HashSet::new));


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

o

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