204

For example, I am currently doing this:

Set<String> setOfTopicAuthors = ....

List<String> list = Arrays.asList( 
    setOfTopicAuthors.toArray( new String[0] ) );

Can you beat this ?

Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
Jacques René Mesrine
  • 41,077
  • 24
  • 60
  • 99
  • 2
    Use `java.util.Collection`: O(0) – Tim Feb 23 '10 at 15:56
  • @Carl, I have to submit the Set into a 3rd party interface which requires a List. @Tim I wish I could change the 3rd party interface to use Collection. – Jacques René Mesrine Feb 24 '10 at 02:08
  • 1
    I see; barring any strange constraints, I'd go with Roger's answer. Though, unless you actually use the List again, I'd skip assigning it to anything (i.e., use foo.api(new ArrayList(listOfTopicAuthors)) instead of foo.api(list)). – Carl Feb 24 '10 at 15:26
  • 2
    @JacquesRenéMesrine: First line of code in question is misleading: Expected: `Set setOfTopicAuthors = ....` Actual: `Set listOfTopicAuthors = ....` – realPK Feb 18 '17 at 20:24
  • Or an alternate way to do the same could be [`List list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new))`](https://stackoverflow.com/a/51545469/1746118), detailed in the linked answer. – Naman Jul 26 '18 at 19:02
  • Java 8 and Java 10 solution : https://stackoverflow.com/a/32179585/1216775 – akhil_mittal Oct 03 '18 at 04:23

6 Answers6

439
List<String> list = new ArrayList<String>(listOfTopicAuthors);
Schildmeijer
  • 19,921
  • 11
  • 59
  • 79
  • 1
    ... and thereby radically defying the Java code conventions: http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html ! :) :) – Håvard Geithus Feb 01 '14 at 00:49
  • after this when I tried to access list element it giving me error, " java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String" ..don;t know why..it's simple list.get(int) that's it ...any suggestion ? – CoDe Jun 20 '14 at 17:45
  • 2
    I believe in Java 7 and above you can omit the type parameter to `ArrayList` yielding: ```List l = new ArrayList<>(listOfTopicAuthors);``` Most concise without using an external library? – Brett Duncavage Oct 30 '14 at 19:37
  • It will throw NullPointerException in case `listOfTopicAuthors` is null. – w35l3y Aug 30 '16 at 20:33
92
List<String> l = new ArrayList<String>(listOfTopicAuthors);
Adamski
  • 51,827
  • 12
  • 103
  • 150
  • 5
    for answering in the same minute as accepted answer and not getting the cred. +1 – jayeffkay Dec 04 '15 at 12:10
  • @Adamski I end up with a list who's index begins at 1 instead of 0, any remedy? – Jack Feb 18 '16 at 22:49
  • 1
    @Jack: That definitely won't be the case. From the Javadoc from java.util.List: "Lists (like Java arrays) are zero based." – Adamski Feb 19 '16 at 14:55
  • @Adamski Thanks for the response. I know lists should be and are zero based which is why this is so strange to me. After converting my set to a list I can't perform any iterative operation on it foreach, sort, etc. I get a NullPointerException, however when I expect my list none of the elements are null, and the only weird I notice is that the index starts at 1. However, if I just create a normal list the index starts at 0. Weird? – Jack Feb 19 '16 at 15:04
  • 1
    @Jack: That sounds very weird. If you post your code as a separate question I'm sure someone will be able to help you out. – Adamski Feb 22 '16 at 08:54
25

Considering that we have Set<String> stringSet we can use following:

Plain Java

List<String> strList = new ArrayList<>(stringSet);

Guava

List<String> strList = Lists.newArrayList(stringSet);

Apache Commons

List<String> strList = new ArrayList<>();
CollectionUtils.addAll(strList, stringSet);

Java 10 (Unmodifiable List)

List<String> strList = List.copyOf(stringSet);
List<String> strList = stringSet.stream().collect(Collectors.toUnmodifiableList());

Java 8 (Modifiable Lists)

import static java.util.stream.Collectors.*;
List<String> stringList1 = stringSet.stream().collect(toList());

As per the doc for the method toList()

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

So if we need a specific implementation e.g. ArrayList we can get it this way:

List<String> stringList2 = stringSet.stream().
                              collect(toCollection(ArrayList::new));

Java 8 (Unmodifiable Lists)

We can make use of Collections::unmodifiableList method and wrap the list returned in previous examples. We can also write our own custom method as:

class ImmutableCollector {
    public static <T> Collector<T, List<T>, List<T>> toImmutableList(Supplier<List<T>> supplier) {
            return Collector.of( supplier, List::add, (left, right) -> {
                        left.addAll(right);
                        return left;
                    }, Collections::unmodifiableList);
        }
}

And then use it as:

List<String> stringList3 = stringSet.stream()
             .collect(ImmutableCollector.toImmutableList(ArrayList::new)); 

Another possibility is to make use of collectingAndThen method which allows some final transformation to be done before returning result:

    List<String> stringList4 = stringSet.stream().collect(collectingAndThen(
      toCollection(ArrayList::new),Collections::unmodifiableList));

One point to note is that the method Collections::unmodifiableList returns an unmodifiable view of the specified list, as per doc. An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view. But the collector method Collectors.unmodifiableList returns truly immutable list in Java 10.

akhil_mittal
  • 18,855
  • 7
  • 83
  • 82
  • I used this to convert a `Set` to a `List`. Could you tell me why this may have happened? I got around it by casting, but I was wondering why it happens. – Ungeheuer Jan 04 '16 at 02:09
  • 1
    Yes, since Java Developers should be using more and more Java 8 features, this answer is better than the above 2 answers. – Shubham Pandey Oct 02 '17 at 07:28
13

Try this for Set:

Set<String> listOfTopicAuthors = .....
List<String> setList = new ArrayList<String>(listOfTopicAuthors); 

Try this for Map:

Map<String, String> listOfTopicAuthors = .....
// List of values:
List<String> mapValueList = new ArrayList<String>(listOfTopicAuthors.values());
// List of keys:
List<String> mapKeyList = new ArrayList<String>(listOfTopicAuthors.KeySet());
Vlad Schnakovszki
  • 7,446
  • 5
  • 74
  • 105
Prabhakar Manthena
  • 2,023
  • 2
  • 14
  • 30
2

If you are using Guava, you statically import newArrayList method from Lists class:

List<String> l = newArrayList(setOfAuthors);
Andrejs
  • 24,146
  • 10
  • 98
  • 92
0

not really sure what you're doing exactly via the context of your code but...

why make the listOfTopicAuthors variable at all?

List<String> list = Arrays.asList((....).toArray( new String[0] ) );

the "...." represents however your set came into play, whether it's new or came from another location.

jp093121
  • 1,663
  • 18
  • 13