Konversi Atur ke Daftar tanpa membuat Daftar baru

503

Saya menggunakan kode ini untuk mengonversi a Setke 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);
}

Saya ingin menghindari membuat daftar baru di setiap iterasi dari loop. Apakah itu mungkin?

Muhammad Imran Tariq
sumber
1
Saya tahu cara mengubah set ke daftar seperti pada Q. Saya ingin menghindari membuat daftar baru setiap kali dalam lingkaran.
Muhammad Imran Tariq
4
Mengapa Anda tidak bisa menambahkan set ke mainList? Mengapa Anda perlu mengonversi Set ke Daftar?
DagR
1
Apakah ini niat Anda untuk membuat Daftar <Daftar <? >>
Hiery Nomus
5
Kamu tidak bisa Pertanyaan Anda mengandung kontradiksi.
Marquis of Lorne

Jawaban:

803

Anda dapat menggunakan metode List.addAll () . Itu menerima Koleksi sebagai argumen, dan set Anda adalah Koleksi.

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

EDIT: sebagai tanggapan terhadap pengeditan pertanyaan.
Sangat mudah untuk melihat bahwa jika Anda ingin memiliki Mapdengan Lists sebagai nilai-nilai, dalam rangka untuk memiliki nilai-nilai k yang berbeda, Anda perlu membuat k daftar yang berbeda.
Jadi: Anda tidak dapat menghindari membuat daftar ini sama sekali, daftar tersebut harus dibuat.

Kemungkinan
penyelesaian : Nyatakan Mapsebagai Map<String,Set>atau Map<String,Collection>sebagai gantinya, dan cukup masukkan set Anda.

ya
sumber
1
maaf itu mainMap bukan daftar. lihat pertanyaan
Muhammad Imran Tariq
@imrantariq: apakah differentKeyNamemengubah setiap iterasi? Apakah Anda benar-benar menginginkan something.size()nilai yang berbeda di peta Anda? Sangat mudah untuk melihat bahwa peta dengan kdaftar sebagai nilai perlu membuat setidaknya kdaftar.
amit
@ imrantariq: dan Anda ingin daftar yang berbeda untuk setiap kunci, saya kira?
amit
@imrantariq: Apa yang Anda minta tidak mungkin. baca edit saya untuk lebih jelasnya.
amit
Ini akan mengembalikan NullPointerException dalam set kasus adalah nol.
w35l3t
411

Gunakan konstruktor untuk mengonversinya:

List<?> list = new ArrayList<?>(set);
zengsn
sumber
21
Dia secara khusus mengatakan dia ingin menghindari ini.
mapeters
3
@make Irrelevant, karena persyaratannya tidak dapat diterapkan.
Marquis of Lorne
16
@ EJP maka jawabannya perlu mengatakan itu, alih-alih hanya menyatakan sesuatu yang OP tidak minta tanpa penjelasan.
mapeters
dia menghindarinya, bahwa konstruktor menggunakan System.arrayCopy, yang membuat salinan dangkal, artinya, hanya menyalin referensi objek ke dalam array yang digunakan untuk membuat daftar. Jika Anda membandingkan kedua koleksi, Anda akan melihat bahwa keduanya mengandung referensi ke objek yang sama.
Gubatron
Ini sebenarnya tidak berfungsi di Android. Ada alasan mengapa
kbluue
84

Juga dari koleksi Guava Collect, Anda dapat menggunakan newArrayList(Collection):

Lists.newArrayList([your_set])

Ini akan sangat mirip dengan jawaban sebelumnya dari amit , kecuali bahwa Anda tidak perlu mendeklarasikan (atau menginisialisasi) listobjek apa pun .

chaiyachaiya
sumber
1
Jika Anda menggunakan jambu biji, ini berguna
vsingh
6
Meskipun Anda tidak secara langsung memanggil konstruktor, metode ini masih memanggil ArrayListkonstruktor.
glen3b
Jika saya tidak mendeklarasikan Daftar, bagaimana saya bisa menggunakan Daftar yang dibuat?
Koray Tugay
@ KorayTugay, Anda mengekstrak Lists.newArrayList ([your_set]) dalam sebuah variabel (lokal atau global). Contoh: Daftar <Foo> fooList = Lists.newArrayList (setOfFoo) Tapi pertanyaan Anda cacat. Jika Anda membuat daftar itu setidaknya secara implisit dinyatakan (jika tidak secara eksplisit).
chaiyachaiya
1
Coba tebak mengapa ini membuat metode ini? Sepertinya tidak lebih baik dari itu new ArrayList<>([your_set]).
DavidS
49

Kita dapat menggunakan satu liner berikut di Java 8:

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

Ini adalah satu contoh kecil:

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());
}
rajadilipkolli
sumber
7
Untuk keterbacaan itu tidak dianjurkan. Misalnya, IntelliJ menyarankan "ArrayList baru <> (set)" dan mencantumkan lebih dari 20 sampel kode serupa dengan dapat diganti dengan cara yang sama.
rrhrg
persis! @rrhrg mana yang lebih baik untuk kinerja jika kita menggunakan set.parallelStream ()?
gaurav
31

solusi paling sederhana

Saya ingin cara yang sangat cepat untuk mengubah set saya ke Daftar dan mengembalikannya, jadi dalam satu baris saya lakukan

 return new ArrayList<Long>(mySetVariable);
Basheer AL-MOMANI
sumber
1
Ini juga yang disarankan IntelliJ IDEA alih-alih aliran api.
Ben
6

Anda dapat menggunakan perubahan satu baris ini: 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()])));
}  
Sahid
sumber
Ukuran dikoreksi karena Objek baru [0] hanya akan menampung satu elemen tetapi Objek baru [set.size ()] akan menampung semua nilai
rajadilipkolli
5

Saya akan lakukan:

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);
}
Jerome L
sumber
5

Karena belum disebutkan sejauh ini, pada Java 10 Anda dapat menggunakan copyOfmetode pabrik baru :

List.copyOf(set);

Dari Javadoc :

Mengembalikan Daftar yang tidak dapat dimodifikasi yang mengandung unsur-unsur Koleksi yang diberikan, dalam urutan iterasi.

beatngu13
sumber
3

Java 8 menyediakan opsi untuk menggunakan stream dan Anda bisa mendapatkan daftar dari Set<String> setStringsebagai:

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

Padahal implementasi internal seperti yang sekarang menyediakan contoh 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);
    }

tapi JDK tidak menjaminnya. Seperti yang disebutkan di sini :

Tidak ada jaminan pada jenis, mutabilitas, serializability, atau keamanan thread dari Daftar yang dikembalikan; jika kontrol lebih besar atas Daftar yang dikembalikan diperlukan, gunakan toCollection (Pemasok).

Jika Anda ingin selalu yakin maka Anda dapat meminta contoh khusus sebagai:

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

Saya membuat staticmetode sederhana :

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

... atau jika Anda ingin mengatur jenis Daftar, Anda dapat menggunakan:

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;
}
thomas.adamjak
sumber
2

Baru-baru ini saya menemukan ini:

ArrayList<T> yourList = Collections.list(Collections.enumeration(yourSet<T>));
Berdiri Yang
sumber
1
Bisakah Anda memperluas atau menguraikan lebih lanjut tentang ini?
Vandal
Collections.list () membuat ArrayList baru: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

Demi kelengkapan ...

Katakan bahwa Anda benar - benar ingin memperlakukan Mapnilai sebagai Lists, tetapi Anda ingin menghindari menyalin Setke dalam Listsetiap waktu.

Misalnya, mungkin Anda memanggil satu fungsi pustaka yang menciptakan Set, tetapi Anda meneruskan Map<String, List<String>>hasil Anda ke fungsi pustaka (yang dirancang dengan buruk tetapi tidak ada di tangan Anda) yang hanya membutuhkan waktu Map<String, List<String>>, meskipun entah bagaimana Anda tahu bahwa operasi itu dilakukan dengan Lists sama-sama berlaku untuk semua Collection(dan dengan demikian ada Set). Dan untuk beberapa alasan Anda perlu menghindari kecepatan / memori overhead menyalin setiap Set ke Daftar.

Dalam kasus ceruk super ini, tergantung pada perilaku (mungkin tidak diketahui) fungsi perpustakaan perlu dari Anda List, Anda mungkin dapat membuat List tampilan atas setiap Set. Perhatikan bahwa ini pada dasarnya tidak aman (karena persyaratan fungsi pustaka dari masing List- masing mungkin bisa berubah tanpa Anda sadari), jadi solusi lain harus lebih disukai. Tapi begini caranya.

Anda akan membuat kelas yang mengimplementasikan Listantarmuka, mengambil Setdalam konstruktor dan menetapkan bahwa Set ke bidang, dan kemudian menggunakan internal itu Setuntuk mengimplementasikan ListAPI (sejauh mungkin, dan diinginkan).

Perhatikan bahwa beberapa perilaku Daftar yang tidak dapat Anda tiru tanpa menyimpan elemen sebagai List, dan beberapa perilaku yang hanya sebagian Anda dapat tiru. Sekali lagi, kelas ini bukan pengganti drop-in yang aman untuk Lists secara umum. Secara khusus, jika Anda tahu bahwa use case membutuhkan operasi terkait indeks atau MUTATING List, pendekatan ini akan berjalan sangat cepat ke selatan.

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);
...
Daniel Avery
sumber
Ini sebenarnya satu-satunya jawaban yang benar-benar menyelesaikan masalah yang disebutkan dalam pertanyaan!
Lii
Anda dapat menerapkan ini dengan cukup mudah dengan memperluas AbstractList
Lii
1

Saya menemukan ini berfungsi dengan baik dan berguna untuk membuat Daftar dari Set.

ArrayList < String > L1 = new ArrayList < String > ();
L1.addAll(ActualMap.keySet());
for (String x: L1) {
    System.out.println(x.toString());
}
Karthic.K
sumber
-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));
}
Muhammad Imran Tariq
sumber
11
Anda tidak pernah menghindari membuat daftar. Kode ini sepele mirip dengan sampel dalam pertanyaan Anda.
Taylor
2
Tapi itu tidak menjawab quezon Anda, tidak ada jawaban.
Marquis of Lorne