Convert Set to List in Java (HashSet to ArrayList and Back)

Learn to convert Set to List in Java with the ArrayList constructor, List.copyOf() and streams, keep or sort the order, and convert a List to a Set.

The same three fruits converted from a HashSet, a LinkedHashSet and a TreeSet into lists with different orders

To convert Set to List in Java, we pass the set to the ArrayList constructor, as in new ArrayList<>(set), which copies every element into a new, modifiable list. For a read-only list, we use List.copyOf(set) or set.stream().toList(), and for the opposite direction, new HashSet<>(list) turns a list into a set and drops its duplicates.

We convert a set to a list when we need what only a list offers, such as access by index, sorting, or an order we control. A typical case is a set of unique tags that a page must show sorted and split into pages of ten.

The following example converts a set of fruits to a list in three ways and turns a list back into a set.

Set<String> fruits = new LinkedHashSet<>(List.of("banana", "apple", "cherry"));
List<String> list = new ArrayList<>(fruits);                     // [banana, apple, cherry]
List<String> readOnly = List.copyOf(fruits);                     // [banana, apple, cherry]
List<String> sorted = fruits.stream().sorted().toList();         // [apple, banana, cherry]
Set<String> unique = new LinkedHashSet<>(List.of("kiwi", "fig", "kiwi"));    // [kiwi, fig]

The converted list keeps the iteration order of the set, which is insertion order for a LinkedHashSet. We cover the order we get from each set type, sorted and unmodifiable results, and the list-to-set direction with its own traps.

1. Convert Set to List with the ArrayList Constructor

The constructor ArrayList(Collection) accepts any collection, so it converts a HashSet, a LinkedHashSet or a TreeSet in one step. It copies the elements in the order the set’s iterator returns them, and the new ArrayList is independent of the set.

Set<Integer> ids = new TreeSet<>(Set.of(30, 10, 20));
List<Integer> idList = new ArrayList<>(ids);                     // [10, 20, 30]
idList.add(40);                                                  // idList = [10, 20, 30, 40]
int first = idList.get(0);                                       // 10

When the target list already exists, addAll() appends the set elements to it instead of creating a new list.

Set<String> extras = new LinkedHashSet<>(List.of("nuts", "honey"));
List<String> toppings = new ArrayList<>(List.of("cream"));
toppings.addAll(extras);                                         // toppings = [cream, nuts, honey]

2. Order of Elements after the Conversion

The list gets the same order in which the set iterates, so the set type decides the order of the list. A HashSet promises no order at all, a LinkedHashSet keeps insertion order, and a TreeSet keeps its elements sorted.

The same three fruits converted from a HashSet, a LinkedHashSet and a TreeSet into lists with different orders
The constructor new ArrayList<>(set) copies the iteration order of the set, so the set type decides the list order
List<String> input = List.of("banana", "apple", "cherry");
List<String> fromLinked = new ArrayList<>(new LinkedHashSet<>(input));    // [banana, apple, cherry]
List<String> fromTree = new ArrayList<>(new TreeSet<>(input));            // [apple, banana, cherry]
List<String> fromHash = new ArrayList<>(new HashSet<>(input));            // all three, order not defined

Code that reads list.get(0) after converting a HashSet works by chance. The order can change when we add elements or move to another JDK version, so tests that compare the list with a fixed order become flaky.

Since Java 21, LinkedHashSet and TreeSet implement SequencedSet from the sequenced collections API. We can read the first and last element without a conversion, or build a list in reverse order with reversed().

SequencedSet<String> recent = new LinkedHashSet<>(List.of("home", "cart", "checkout"));
String firstPage = recent.getFirst();                            // "home"
List<String> newestFirst = new ArrayList<>(recent.reversed());   // [checkout, cart, home]

3. Convert a Set to an Unmodifiable List

When the list must not change, we create an unmodifiable copy. Java offers two methods, and they differ only in how they treat null elements.

  • The method List.copyOf() (Java 10) throws NullPointerException if the set contains null.
  • The method Stream.toList() (Java 16) accepts null elements.
Set<String> sizes = new LinkedHashSet<>(Arrays.asList("S", null, "M"));
List<String> viaStream = sizes.stream().toList();                 // [S, null, M]
List<String> viaCopyOf = List.copyOf(sizes);                      // NullPointerException

Both lists throw UnsupportedOperationException on add(), remove() or set(). A class that returns its internal set to callers as a list uses one of them, so callers cannot change the data, as described in collecting a stream into an immutable collection.

4. Convert a Set to a Sorted List

An online store keeps the tags of all products in a HashSet, because a tag must appear once no matter how many products use it. The tag filter on the website needs those tags in alphabetical order, so the backend converts the set to a sorted list before it sends the JSON response.

Set<String> tags = new HashSet<>(Set.of("sale", "new", "eco", "kids"));
List<String> filterTags = tags.stream().sorted().toList();                         // [eco, kids, new, sale]
List<String> byLength = new ArrayList<>(tags);
byLength.sort(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()));
String result = byLength.toString();                                               // "[eco, new, kids, sale]"

A sorted stream fits when the list is read-only. For a modifiable list, we copy the set into an ArrayList and call sort(), which also accepts any Comparator, as shown in sorting an ArrayList.

5. Convert a List to a Set

The opposite conversion uses the constructor of the set class. Since a set holds each element once, the conversion removes duplicates, and the set type decides the order again.

List<Integer> votes = List.of(3, 1, 3, 2, 1);
Set<Integer> hashed = new HashSet<>(votes);                       // 1, 2 and 3, order not defined
Set<Integer> inOrder = new LinkedHashSet<>(votes);                // [3, 1, 2]
Set<Integer> ascending = new TreeSet<>(votes);                    // [1, 2, 3]
Set<Integer> frozen = Set.copyOf(votes);                          // 1, 2 and 3, unmodifiable
int count = hashed.size();                                        // 3

The method Set.copyOf() drops duplicates without an exception, but the factory method Set.of() throws IllegalArgumentException when we pass the same element twice. For streams, Collectors.toSet() does not guarantee the set type, so we use Collectors.toCollection(LinkedHashSet::new) when the order matters.

Set<String> fromCopy = Set.copyOf(List.of("a", "a"));               // [a]
Set<String> fromOf = Set.of("a", "a");                                // IllegalArgumentException: duplicate element: a
Set<String> fromStream = Stream.of("b", "a", "b").collect(Collectors.toCollection(LinkedHashSet::new));    // [b, a]

Converting a list to a set and back is the classic way to remove duplicates from a list. With a LinkedHashSet in the middle, the result keeps the first occurrence of each element in the original order.

6. Using Guava

Projects that use Guava can call Lists.newArrayList(set) for a modifiable list and ImmutableList.copyOf(set) for an immutable one. Both give the same result as the JDK methods in section 1 and section 3, so Guava is not needed for this conversion alone.

Set<String> fruits = new TreeSet<>(Set.of("plum", "lime"));
List<String> guavaList = Lists.newArrayList(fruits);              // [lime, plum]
List<String> guavaImmutable = ImmutableList.copyOf(fruits);       // [lime, plum]

7. Set and List Conversion FAQs

Search results for Set to List conversion show the same follow-up questions about order, indexes and arrays.

7.1. Does converting a HashSet to an ArrayList keep the order?

The list keeps the iteration order of the HashSet, but that order is not defined, so it can differ from the insertion order and from the sorted order. We use a LinkedHashSet for insertion order or a TreeSet for sorted order.

7.2. Can we get an element by index from a Set?

No. The Set interface has no get(int) method, because most sets have no positions. We convert to a list for index access, or we use getFirst() and getLast() on a LinkedHashSet or TreeSet since Java 21.

7.3. How do we convert a Set to an array?

We call toArray() with an array constructor reference, which returns an array of the right type.

Set<String> colors = new TreeSet<>(Set.of("red", "blue"));
String[] array = colors.toArray(String[]::new);                   // [blue, red]

7.4. Is new ArrayList<>(set) or set.stream().toList() faster?

Both copy every element once, so both take time proportional to the size of the set. The real difference is the result, because the constructor returns a modifiable ArrayList and toList() returns an unmodifiable list.

8. Conclusion

We convert a Set to a List with new ArrayList<>(set) when the list must change, and with List.copyOf() or stream().toList() when it must not. The list always gets the iteration order of the set, so we pick a LinkedHashSet or a TreeSet when the order matters, or sort the result.

In the other direction, a set constructor turns a list into a set and drops the duplicates. The method Set.copyOf() accepts duplicates, whereas Set.of() rejects them with IllegalArgumentException.

9. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.