Convert Set to List without creating new List

JavaPerformanceListSet

Java Problem Overview


I am using this code to convert a Set to a 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);
}

I want to avoid creating a new list in each iteration of the loop. Is that possible?

Java Solutions


Solution 1 - Java

You can use the List.addAll() method. It accepts a Collection as an argument, and your set is a Collection.

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

EDIT: as respond to the edit of the question.
It is easy to see that if you want to have a Map with Lists as values, in order to have k different values, you need to create k different lists.
Thus: You cannot avoid creating these lists at all, the lists will have to be created.

Possible work around:
Declare your Map as a Map<String,Set> or Map<String,Collection> instead, and just insert your set.

Solution 2 - Java

Use constructor to convert it:

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

Solution 3 - Java

Also from Guava Collect library, you can use newArrayList(Collection):

Lists.newArrayList([your_set])

This would be very similar to the previous answer from amit, except that you do not need to declare (or instanciate) any list object.

Solution 4 - Java

We can use following one liner in Java 8:

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

Here is one small example:

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

Solution 5 - Java

> the simplest solution

I wanted a very quick way to convert my set to List and return it, so in one line I did

 return new ArrayList<Long>(mySetVariable);

Solution 6 - Java

Since it hasn't been mentioned so far, as of Java 10 you can use the new copyOf factory method:

List.copyOf(set);

From the Javadoc:

>Returns an unmodifiable List containing the elements of the given Collection, in its iteration order.

Note that this creates a new list (ImmutableCollections$ListN to be precise) under the hood by

  1. calling Collection#toArray() on the given set and then
  2. putting these objects into a new array.

Solution 7 - Java

I would do :

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

Solution 8 - Java

You could use this one line change: 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()])));
}  

  

Solution 9 - Java

I create simple static method:

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

... or if you want to set type of List you can use:

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

Solution 10 - Java

Java 8 provides the option of using streams and you can get a list from Set<String> setString as:

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

Though the internal implementation as of now provides an instance of 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);
    }

but JDK does not guarantee it. As mentioned here:

> There are no guarantees on the type, mutability, serializability, or > thread-safety of the List returned; if more control over the returned > List is required, use toCollection(Supplier).

In case you want to be sure always then you can request for an instance specifically as:

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

Solution 11 - Java

Recently I found this:

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

Solution 12 - Java

For the sake of completeness...

Say that you really do want to treat the Map values as Lists, but you want to avoid copying the Set into a List each time.

For instance, maybe you are calling one library function that creates a Set, but you are passing your Map<String, List<String>> result to a (poorly-designed but out of your hands) library function that only takes Map<String, List<String>>, even though somehow you know that the operations it does with the Lists are equally applicable to any Collection (and thus any Set). And for some reason you need to avoid the speed/memory overhead of copying each Set to a List.

In this super niche case, depending on the (maybe unknowable) behavior the library function needs out of your Lists, you may be able to create a List view over each Set. Note that this is inherently unsafe (because the library function's requirements from each List could presumably change without you knowing), so another solution should be preferred. But here's how you'd do it.

You'd create a class that implements the List interface, takes a Set in the constructor and assigns that Set to a field, and then uses that internal Set to implement the List API (to the extent possible, and desired).

Note that some List behavior you simply will not be able to imitate without storing the elements as a List, and some behavior you will only partially be able to imitate. Again, this class is not a safe drop-in replacement for Lists in general. In particular, if you know that the use case requires index-related operations or MUTATING the List, this approach would go south very fast.

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

Solution 13 - Java

I found this working fine and useful to create a List from a Set.

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

Solution 14 - Java

You convert Set to List without adding ordering information (like sorting) just to store it in the map.

Because Set is unordered and no ordering information is added, List should not be used, as it will contain randomly ordered data and all it's methods that are related to ordered data will be ambiguous.

You should use Collection interface instead, that accepts both Set and List in the map. This way, no additional memory is required as you use polymorphism instead of copying data.

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

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

> Disclaimer: my edit to a similar answer was rejected so I added my own answer with additional information

Solution 15 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMuhammad Imran TariqView Question on Stackoverflow
Solution 1 - JavaamitView Answer on Stackoverflow
Solution 2 - JavazengsnView Answer on Stackoverflow
Solution 3 - JavachaiyachaiyaView Answer on Stackoverflow
Solution 4 - JavarajadilipkolliView Answer on Stackoverflow
Solution 5 - JavaBasheer AL-MOMANIView Answer on Stackoverflow
Solution 6 - Javabeatngu13View Answer on Stackoverflow
Solution 7 - JavaJerome LView Answer on Stackoverflow
Solution 8 - JavaSaheedView Answer on Stackoverflow
Solution 9 - Javathomas.adamjakView Answer on Stackoverflow
Solution 10 - Javaakhil_mittalView Answer on Stackoverflow
Solution 11 - JavaStand YangView Answer on Stackoverflow
Solution 12 - JavaDaniel AveryView Answer on Stackoverflow
Solution 13 - JavaKarthic.KView Answer on Stackoverflow
Solution 14 - JavacdalxndrView Answer on Stackoverflow
Solution 15 - JavaMuhammad Imran TariqView Answer on Stackoverflow