Yeni Liste oluşturmadan Kümeyi Listeye Dönüştür


503

Ben dönüştürmek için bu kodu kullanıyorum Seta List:

Map<String, List<String>> mainMap = new HashMap<>();

for (int i=0; i < something.size(); i++) {
  Set<String> set = getSet(...); //returns different result each time
  List<String> listOfNames = new ArrayList<>(set);
  mainMap.put(differentKeyName, listOfNames);
}

Döngünün her yinelemesinde yeni bir liste oluşturmaktan kaçınmak istiyorum. Mümkün mü?


1
Küme liste Q dönüştürmek için bir yol biliyorum. Her döngüde yeni liste oluşturmaktan kaçınmak istiyorum.
Muhammed İmran Tarık

4
Kümeyi neden mainList'e ekleyemiyorsun? Kümeyi neden bir Listeye dönüştürmeniz gerekiyor?
DagR


5
Yapamazsın. Sorunuz açısından bir çelişki var.
Lorne Marquis

Yanıtlar:


802

Sen kullanabilirsiniz List.addAll () yöntemini. Bir Koleksiyonu argüman olarak kabul eder ve kümeniz bir Koleksiyon'dur.

List<String> mainList = new ArrayList<String>();
mainList.addAll(set);

EDIT: sorunun düzenlemesine yanıt olarak. S olarak
a Mapile sahip olmak istiyorsanız List, k farklı değerlere sahip olmak için k farklı liste oluşturmanız gerektiğini görmek kolaydır .
Bu nedenle: Bu listeleri oluşturmaktan kaçınamazsınız, listelerin oluşturulması gerekir.

Olası iş çevresinde:
Declare Mapbir şekilde Map<String,Set>ya da Map<String,Collection>onun yerine ve sadece set yerleştirin.


1
üzgünüm mainMap liste değildi. soruya bakın
Muhammad Imran Tariq

@imrantariq: differentKeyNameher yinelemeyi değiştiriyor mu? Aslında something.size()haritalarınızda farklı olası değerler mi istiyorsunuz ? kEn az kliste oluşturmak için değerleri olan listeler içeren bir haritanın görülmesi kolaydır .
amit

@imrantariq: ve her bir anahtar için farklı bir liste mi istiyorsunuz?
amit

@imrantariq: İstediğiniz şey imkansız. daha fazla ayrıntı için düzenlememi okuyun.
amit

Küme kümesi null olduğunda NullPointerException döndürür.
w35l3y

411

Dönüştürücüyü dönüştürmek için kullanın:

List<?> list = new ArrayList<?>(set);

21
Özellikle bundan kaçınmak istediğini söyledi.
mapeters

3
@mook İlgisiz olduğu için ilgisiz.
Lorne Marquis

16
@EJP sonra cevabının, OP'nin herhangi bir açıklama yapmadan istemediği bir şeyi belirtmek yerine söylemeliydi.
mapeters

bundan kaçınıyor, bu yapıcı sığ kopyalar üreten System.arrayCopy kullanıyor, yani, nesnelerin referanslarını sadece listeyi oluşturmak için kullanılan diziye kopyalıyor. Her iki koleksiyonu da karşılaştırırsanız, her ikisinin de aynı nesnelere referans içerdiğini görürsünüz.
Gubatron

Bu aslında Android'de çalışmaz. Neden?
kbluue

84

Ayrıca Guava Collect kütüphanesinden şunları kullanabilirsiniz newArrayList(Collection):

Lists.newArrayList([your_set])

Bu, herhangi bir nesneyi beyan etmeniz (veya başlatmanız) gerekmemesi dışında, amit'in önceki cevabına çok benzer olacaktır list.


1
Guava kullanıyorsanız, bu kullanışlı
vsingh

6
Yapıcıyı doğrudan çağırmamanıza rağmen, bu yöntem yine de yapıcıyı çağırır ArrayList.
glen3b

Bir Liste bildirmezsem, oluşturulan Listeyi nasıl kullanabilirim?
Koray Tugay

@KorayTugay, Lists.newArrayList ([your_set]) değişkeninde (yerel veya global) ayıklayabilirsiniz . Örn: List <Foo> fooList = Lists.newArrayList (setOfFoo) Ama sorunuz hatalı. Bir liste oluşturursanız, en azından örtük olarak bildirilir (açıkça değilse).
chaiyachaiya

1
Bunun neden bu yöntemi yaptığını tahmin ettiniz mi? Bundan daha iyi görünmüyor new ArrayList<>([your_set]).
DavidS

49

Java 8'de aşağıdaki bir astarı kullanabiliriz:

List<String> list = set.stream().collect(Collectors.toList());

İşte küçük bir örnek:

public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("A");
        set.add("B");
        set.add("C");
        List<String> list = set.stream().collect(Collectors.toList());
}

7
Okunabilirlik için önerilmez. Örneğin, IntelliJ "yeni ArrayList <> (set)" önerir ve 20'den fazla benzer kod örneğini aynı şekilde değiştirebilir.
rrhrg

kesinlikle! @rrhrg set.parallelStream () kullanırsak performans için daha iyidir?
gaurav

31

en basit çözüm

Setimi List'e dönüştürmek ve geri döndürmek için çok hızlı bir yol istedim, bu yüzden bir satırda

 return new ArrayList<Long>(mySetVariable);

1
IntelliJ IDEA'nın api akışları yerine önerdiği de budur.
Ben

6

Bu tek satırlık değişikliği kullanabilirsiniz: Arrays.asList(set.toArray(new Object[set.size()]))

Map<String, List> mainMap = new HashMap<String, List>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); 
  mainMap.put(differentKeyName, Arrays.asList(set.toArray(new Object[set.size()])));
}  

Yeni Object [0] yalnızca bir öğe içerecek, ancak new Object [set.size ()] tüm değerleri
tutacağı için düzeltildi

5

Yapardım :

Map<String, Collection> mainMap = new HashMap<String, Collection>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); //return different result each time
  mainMap.put(differentKeyName,set);
}

5

Şimdiye kadar bahsedilmediğinden, Java 10'dan itibaren yeni copyOffabrika yöntemini kullanabilirsiniz:

List.copyOf(set);

Gönderen Javadoc :

Belirli bir Koleksiyonun öğelerini yineleme sırasında içeren değiştirilemez bir Liste döndürür .


3

Java 8 akışları kullanma seçeneği sunar ve aşağıdakilerden bir liste alabilirsiniz Set<String> setString:

List<String> stringList = setString.stream().collect(Collectors.toList());

Her ne kadar şu andan itibaren iç uygulama şu örneği sağlıyor ArrayList:

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }

ancak JDK bunu garanti etmez. As söz burada :

Döndürülen Listenin türü, değiştirilebilirliği, serileştirilebilirliği veya iş parçacığı güvenliği konusunda hiçbir garanti yoktur; döndürülen Liste üzerinde daha fazla denetim gerekiyorsa, toCollection (Tedarikçi) öğesini kullanın.

Her zaman emin olmak istiyorsanız, özellikle aşağıdaki gibi bir örnek talep edebilirsiniz:

List<String> stringArrayList = setString.stream()
                     .collect(Collectors.toCollection(ArrayList::new));

2

Basit bir staticyöntem oluşturuyorum :

public static <U> List<U> convertSetToList(Set<U> set)
{
    return new ArrayList<U>(set);
}

... veya Liste türünü ayarlamak istiyorsanız şunları kullanabilirsiniz:

public static <U, L extends List<U>> List<U> convertSetToList(Set<U> set, Class<L> clazz) throws InstantiationException, IllegalAccessException
{
    L list = clazz.newInstance();
    list.addAll(set);
    return list;
}

2

Son zamanlarda bunu buldum:

ArrayList<T> yourList = Collections.list(Collections.enumeration(yourSet<T>));

1
Bununla ilgili daha fazla ayrıntı verebilir misiniz?
Vandal

Collections.list () yeni bir ArrayList oluşturur:public static <T> ArrayList<T> list(Enumeration<T> e) { ArrayList<T> l = new ArrayList<>(); while (e.hasMoreElements()) l.add(e.nextElement()); return l; }
Artem Lukanin

2

Bütünlüğü uğruna...

Bunu Say gerçekten yapmak tedavi etmek istiyorum Mapgibi değerleri Lists, ancak kopyalama önlemek istiyorsanız Setbir içine Listher zaman.

Örneğin, belki bir oluşturur tek kütüphane işlevini aradığınız Set, ancak geçiyoruz Map<String, List<String>>sadece alır (kötü tasarlanmış ancak senin elinde) kütüphane işlevi sonucu Map<String, List<String>>olsa nasılsa biliyor işlemler onunla yaptığı Lists, herhangi biri Collection(ve dolayısıyla herhangi biri Set) için eşit olarak uygulanabilir . Ve bazı nedenlerden dolayı , her bir Seti bir Listeye kopyalamanın hız / bellek yükünden kaçınmanız gerekir.

Bu süper niş durumda, kütüphane fonksiyonunun sizin ihtiyaç duyduğunuz (belki de bilinemez) davranışa bağlı olarak, her Set üzerinde Listbir List görünüm oluşturabilirsiniz . Bunun doğal olarak güvensiz olduğuna dikkat edin (çünkü kütüphane fonksiyonunun her birinden gelen gereksinimler Listmuhtemelen bilmeden değişebilir), bu nedenle başka bir çözüm tercih edilmelidir. Ama işte böyle yapardın.

ListArabirimi uygulayan, yapıcıyı alan Setve bu Kümeyi bir alana atayan ve daha sonra bu iç öğeyi API'yi (mümkün ve istenen ölçüde) Setuygulamak için kullanırsınız List.

Bazı Liste davranışlarının öğeleri a olarak kaydetmeden taklit edemeyeceğinizi Listve bazı davranışları sadece kısmen taklit edebileceğinizi unutmayın. Yine, bu sınıf Listgenel olarak s için güvenli bir yedek yerine geçmez . Özellikle, kullanım durumunun dizinle ilgili işlemler veya MUTATING gerektirdiğini biliyorsanız List, bu yaklaşım güneye çok hızlı gider.

public class ListViewOfSet<U> implements List<U> {
    private final Set<U> wrappedSet;
    public ListViewOfSet(Set<U> setToWrap) { this.wrappedSet = setToWrap; }

    @Override public int size() { return this.wrappedSet.size(); }
    @Override public boolean isEmpty() { return this.wrappedSet.isEmpty(); }
    @Override public boolean contains(Object o) { return this.wrappedSet.contains(o); }
    @Override public java.util.Iterator<U> iterator() { return this.wrappedSet.iterator(); }
    @Override public Object[] toArray() { return this.wrappedSet.toArray(); }
    @Override public <T> T[] toArray(T[] ts) { return this.wrappedSet.toArray(ts); }
    @Override public boolean add(U e) { return this.wrappedSet.add(e); }
    @Override public boolean remove(Object o) { return this.wrappedSet.remove(o); }
    @Override public boolean containsAll(Collection<?> clctn) { return this.wrappedSet.containsAll(clctn); }
    @Override public boolean addAll(Collection<? extends U> clctn) { return this.wrappedSet.addAll(clctn); }
    @Override public boolean addAll(int i, Collection<? extends U> clctn) { throw new UnsupportedOperationException(); }
    @Override public boolean removeAll(Collection<?> clctn) { return this.wrappedSet.removeAll(clctn); }
    @Override public boolean retainAll(Collection<?> clctn) { return this.wrappedSet.retainAll(clctn); }
    @Override public void clear() { this.wrappedSet.clear(); }
    @Override public U get(int i) { throw new UnsupportedOperationException(); }
    @Override public U set(int i, U e) { throw new UnsupportedOperationException(); }
    @Override public void add(int i, U e) { throw new UnsupportedOperationException(); }
    @Override public U remove(int i) { throw new UnsupportedOperationException(); }
    @Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
    @Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
    @Override public ListIterator<U> listIterator() { throw new UnsupportedOperationException(); }
    @Override public ListIterator<U> listIterator(int i) { throw new UnsupportedOperationException(); }
    @Override public List<U> subList(int i, int i1) { throw new UnsupportedOperationException(); }
}

...
Set<String> set = getSet(...);
ListViewOfSet<String> listOfNames = new ListViewOfSet<>(set);
...

Aslında soruda belirtilen sorunu gerçekten çözen tek cevap budur!
Lii

Bunu, AbstractList
Lii

1

Ben bu Set iyi bir Liste oluşturmak için iyi ve yararlı buldum.

ArrayList < String > L1 = new ArrayList < String > ();
L1.addAll(ActualMap.keySet());
for (String x: L1) {
    System.out.println(x.toString());
}

-15
Map<String, List> mainMap = new HashMap<String, List>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); //return different result each time
  mainMap.put(differentKeyName, new ArrayList(set));
}

11
Listeyi oluşturmaktan kaçınmadınız. Bu kod, sorunuzdaki örneğe çok benzer.
Taylor

2
Ama quezonunuza cevap vermiyor, bir cevap yok.
Lorne Marquis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.