Kaip inicijuoti „HashSet“ vertes pagal statybą?

Turiu sukurti Set su pradinėmis reikšmėmis.

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

Ar yra būdas tai padaryti vienoje kodo eilutėje? Pavyzdžiui, tai naudinga galutiniam statiniam laukui.

593
11 янв. Sergas surengtas sausio 11 d 2010-01-11 15:31 '10, 15:31, 2010-01-11 15:31
@ 22 atsakymai

Aš naudoju spartųjį klavišą, jis nėra labai efektyvus, bet tinka vienai eilutei:

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

Vėlgi, tai nėra labai veiksminga, nes sukuriate masyvą, konvertuojate jį į sąrašą ir naudodami šį sąrašą sukuriate rinkinį.

Kai inicijuojate statinius galutinius rinkinius, paprastai rašau tai:

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

Šiek tiek mažiau bjaurus ir efektyvus statinis inicializavimas nesvarbu.

769
11 янв. atsakymas pateikiamas Genadijus 11-osios. 2010-01-11 15:38 '10, 15:38, 2010-01-11 15:38

Surinkimo literatūra buvo suplanuota „Java 7“, bet ne. Taigi nieko nebuvo automatiškai.

Galite naudoti guavos rinkinius:

 Sets.newHashSet("a", "b", "c") 
border=0

Arba galite naudoti šią sintaksę, kuri sukurs anoniminę klasę, tačiau ji yra nulaužta:

 Set<String> h = new HashSet<String>() {{ add("a"); add("b"); }}; 
310
11 янв. Bozho atsakė į sausio 11 d 2010-01-11 15:34 '10, 15:34, 2010-01-11 15:34

„Java 8“ naudoju:

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

Tai suteikia jums Set kintamąjį, iš anksto inicijuotą „a“ ir „b“ simboliais. Atkreipkite dėmesį, kad nors JDK 8 jis grąžina „ HashSet , specifikacija negarantuoja, ir tai gali pasikeisti ateityje. Jei konkrečiai norite „ HashSet , atlikite tai:

 Set<String> set = Stream.of("a", "b") .collect(Collectors.toCollection(HashSet::new)); 
161
13 янв. Atsakymą pateikė Christian Ullenboom sausio 13 d. 2014-01-13 07:49 '14 at 7:49 2014-01-13 07:49

„Java 10“ naudojimas (nekintami rinkiniai)

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

Čia kolektorius faktiškai grąžina nepakeičiamą rinkinį, įvestą „Java 9“, kaip matyti iš set → (Set<T>)Set.of(set.toArray()) šaltinio kode.

„Java 9“ naudojimas (nekintami rinkiniai)

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

Turime 12 perkrautų šios gamyklos metodo versijų:

static <E> Set<E> of()

static <E> Set<E> of(E e1)

static <E> Set<E> of(E e1, E e2)

// .... ir pan

static <E> Set<E> of(E... elems)

Tada kyla natūralus klausimas: kodėl mums reikia perkrautų versijų, kai turime var-args ? Atsakymas yra toks: kiekvienas var-arg metodas sukuria masyvą viduje, o perkrautos versijos vengs nereikalingų objektų kūrimo ir taip pat išgelbės mus nuo šiukšlių surinkimo išlaidų.

„Java 8“ (modifikuojami rinkiniai) naudojimas

Stream“ naudojimas „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)); 

„Java 8“ naudojimas (nekintami rinkiniai)

Naudojant kolekcijas.unmodifiableSet - mes galime naudoti „ Collections.unmodifiableSet kaip:

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

Bet tai atrodo šiek tiek nepatogiai, ir mes galime rašyti savo kolekcionierių, kaip šis:

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

Ir tada naudokite jį kaip:

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

Naudokite „Collectors.collectingAndThen“. Kitas būdas yra naudoti „ Collectors.collectingAndThen metodą, kuris leidžia atlikti papildomus galutinius pakeitimus:

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

Jei rūpinamės tik „ Set mes galime naudoti „ Collectors.toSet() vietoj „ Collectors.toCollection(HashSet::new) .


Pažymėtina , kad Collections::unmodifiableSet grąžina Collections::unmodifiableSet nurodyto rinkinio vaizdą pagal dokumentą . Nepakeičiamas vaizdų rinkinys yra kolekcija, kurios negalima keisti, taip pat yra atsarginės kolekcijos atvaizdas. Atminkite, kad atsarginės kolekcijos pakeitimai vis dar galimi, ir jei jie įvyksta, jie matomi per nekintamą vaizdą. Tačiau „ Collectors.unmodifiableSet metodas grąžina „ Java 10“ tikrai nepakeistą rinkinį.

89
24 мая '16 в 9:36 2016-05-24 09:36 atsakymas pateikiamas i_am_zero gegužės 24 d. 16, 9:36 2016-05-24 09:36

Yra keletas būdų:

Dvigubo atramos inicializavimas

Tai yra metodas, kuris sukuria anoniminę vidinę klasę, kurioje yra instancijos iniciatorius, kuris sukuria String sau kurdamas pavyzdį:

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

Turėkite omenyje, kad tai tikrai sukuria naują „ HashSet kiekvieną kartą, kai jis bus naudojamas, nors jam nereikia aiškiai parašyti naujo poklasio.

Naudingumas

Rašyti metodą, kuris grąžina Set , kuris inicijuojamas būtinais elementais, nėra taip sunku rašyti:

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

Anksčiau minėtas kodas naudoja tik String , tačiau neturėtų būti pernelyg sunku leisti naudoti bet kokio tipo, naudojant bendrus vaistus.

Naudokite biblioteką

Daugelis bibliotekų turi patogumo metodą rinkti objektus.

Pavyzdžiui, „ Google“ kolekcijose yra „ Sets.newHashSet(T...) , kuris užpildys „ HashSet elementą su tam tikro tipo elementais.

82
11 янв. Atsakymą pateikė coobird Jan 11 2010-01-11 15:34 '10, 15:34, 2010-01-11 15:34

Jei rinkinyje yra tik viena pradinė vertė, pakaks:

 Set<String> h = Collections.singleton("a"); 
27
05 окт. atsakymą pateikė Lu55 05 okt. 2015-10-05 10:51 '15, 10:51 val. 2015-10-05 10:51

Tai galite padaryti „Java 6“:

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

Bet kodėl? Nemanau, kad tai būtų lengviau skaitoma nei aiškus elementų papildymas.

26
11 янв. Atsakymas į Jason Nichols sausio 11 d 2010-01-11 15:36 '10, 15:36, 2010-01-11 15:36

Manau, kad labiausiai skaityti yra tik „Google Guava“:

 Set<String> StringSet = Sets.newSet("a", "b", "c"); 
23
29 окт. atsakymas pateikiamas LanceP 29 okt. 2014-10-29 21:05 '14, 21:05 2014-10-29 21:05

Naudodami „Java 9“ galite atlikti šiuos veiksmus:

 Set.of("a", "b"); 

ir jūs gaunate nepakeistą rinkinį, kuriame yra elementų. Išsamesnės informacijos rasite „Set“ sąsajos „ Oracle“ dokumentacijoje .

20
05 июля '17 в 12:30 2017-07-05 12:30 Atsakymą davė Mathias Bader liepos 17 d. 17 val. 12:30 2017-07-05 12:30

Vienas iš patogiausių būdų yra naudoti universalų metodą Kolekcionavimas.addAll () , kuris priima kolekciją ir varargus:

 Set<String> h = new HashSet<String>(); Collections.addAll(h, "a", "b"); 
19
22 нояб. Michael Berdyshev atsakymas lapkričio 22 d 2016-11-22 05:41 '16 at 5:41 am 2016-11-22 05:41

Apibendrinant „ coobird“ atsakymo įrankio funkciją sukurti naują „ 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; } 
14
30 авг. Mark Elliot atsakymas rugpjūčio 30 d 2010-08-30 02:49 '10 at 2:49 2010-08-30 02:49

Jei „Set“ tipo rinkinys yra sąrašas, yra „Java“ gamyklos metodas (pradedant nuo 1.5 versijos):

 Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... ); 
10
23 дек. Atsakymą pateikė Heri . 2015-12-23 10:16 '15, 10:16 2015-12-23 10:16
 import com.google.common.collect.Sets; Sets.newHashSet("a", "b"); 

arba

 import com.google.common.collect.ImmutableSet; ImmutableSet.of("a", "b"); 
5
14 июля '17 в 19:29 2017-07-14 19:29 atsakymą pateikė Bryan Correll, liepos 17 d. 17, 19:29 2017-07-14 19:29

Naudojant „ Eclipse“ rinkinius, yra keli skirtingi būdai, kaip inicijuoti Set , kuriame vienoje išraiška yra simboliai „a“ ir „b“, „Eclipse“ kolekcijose yra konteineriai tiek objektui, tiek primityviems tipams, todėl parodiau, kaip galite naudoti „ Set<String> arba CharSet , be CharSet , nekintamų, sinchronizuotų ir nekintamų abiejų versijų.

 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“ kolekcijos yra suderinamos su „Java 5-8“.

Pastaba Aš esu „Eclipse“ kolekcijų pardavėjas.

5
29 февр. atsakymą pateikė Donaldas Raabas vasario 29 d. 2016-02-29 23:41 '16 at 11:41 pm 2016-02-29 23:41

(negraži) dvigubos santuokos inicijavimas be šalutinio poveikio:

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

Tačiau kai kuriais atvejais, jei paminėjome, kad geras kvapas padaryti galutines kolekcijas nepakeičiamas, tai gali būti tikrai naudinga:

 final Set<String> a = Collections.unmodifiableSet(new HashSet<String>(){{ add("1"); add("2"); }}) 
4
09 авг. atsakymas duotas egorlitvinenko rugpjūčio 9 d. 2017-08-09 22:31 '17, 10:31 pm 2017-08-09 22:31

Šiek tiek sumažintas, bet veikia su „Java 5“:

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

Naudokite pagalbininko metodą, kad jį būtų galima perskaityti:

 Set<String> h = asSet ("a", "b"); public Set<String> asSet(String... values) { return new HashSet<String>(java.util.Arrays.asList(values)); } 
4
11 янв. Atsakymą pateikė Aaron Digulla sausio 11 dieną. 2010-01-11 15:38 '10, 15:38, 2010-01-11 15:38

Naudodami „ Java 8“ galime sukurti „ HashSet kaip:

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

Ir jei norime nustatyti nepakeistą rinkinį, galime sukurti pagalbinį metodą, kaip:

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

Šis metodas gali būti naudojamas kaip:

  Stream.of("A", "B", "C", "D").collect(toImmutableSet(HashSet::new)); 
3
08 дек. atsakymas suteiktas rakhi 08 dec. 2017-12-08 12:24 '17, 12:24 pm 2017-12-08 12:24

Išleidus ir gamyklinius metodus , tai galbūt yra švaresnis būdas, pavyzdžiui:

 Set set2 = Set.of("a", "b", "c"); 
3
27 сент. atsakymas pateikiamas nullpointer 27 sep . 2017-09-27 20:55 '17, 8:55 pm 2017-09-27 20:55

Tiesiog greitas pastaba, nesvarbu, koks čia nurodytas geras metodas, jūs baigsite su numatytuoju, kuris paprastai yra nepakeistas (pvz., Numatytoji vertė, sukurta bibliotekoje), gerai sekti šį modelį:

 // Initialize default values with the method you prefer, even in a static block // It 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; 

Privalumas priklauso nuo to, kiek kartų sukūrėte šioje klasėje, ir kaip tikėtina, kad bus pakeistos numatytosios vertės.

Jei nuspręsite sekti šį modelį, taip pat galite pasirinkti nustatytą inicijavimo metodą, kuris yra labiausiai įskaitomas. Kadangi mikrodifferencija tarp skirtingų metodų efektyvumo tikriausiai nesvarbu, nes jūs inicijuosite rinkinį tik vieną kartą.

3
11 нояб. atsakymą pateikė Amr Mostafa 11 nov. 2015-11-11 12:21 '15, 12:21 val. 2015-11-11 12:21

Galite inicijuoti statinį bloką:

 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); } 
1
17 мая '17 в 9:24 2017-05-17 09:24 atsakymas pateikiamas Ups 17 d., 17 val

Čia gali būti naudinga „Builder“ šablonas. Šiandien turėjau tą pačią problemą. kur man reikia „Set“ mutacijos operacijų, kad grąžintumėte nuorodą į „Set“ objektą, kad galėčiau perduoti jį superklasės konstruktoriui, kad jie taip pat galėtų toliau pridėti prie to paties rinkinio, savo ruožtu sukuriant naują „StringSetBuilder“ iš „Set“, kuris yra tik sukurta vaikų klasė Statytojo klasė, kurią parašiau, atrodo taip (mano atveju tai yra statiška išorinės klasės vidinė klasė, tačiau ji taip pat gali būti savarankiška klasė):

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

Atkreipkite dėmesį į addAll() ir add() , kurie nustato grąžinamuosius analogus Set.add() ir Set.addAll() . Galiausiai, atkreipkite dėmesį į build() metodą, kuris grąžina nuorodą į „Set“, kurį statytojas įdeda. Toliau parodoma, kaip naudoti šį rinkinį:

 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()); } } 
0
03 нояб. Atsakymą pateikė Jose Quijada 03.11 . 2017-11-03 19:44 '17, 19:44 pm 2017-11-03 19:44

Tai elegantiškas sprendimas:

 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); } }; } 
0
12 мая '15 в 17:37 2015-05-12 17:37 atsakymas buvo perduotas ToxiCore gegužės 12 d., 15 val. 17:37 2015-05-12 17:37