0

Is there a way to convert a List<Set<String>> mainList to a plain List, without iterating over elements?

For example this one has value:

mainList = {ArrayList@705}  size = 2
 0 = {HashSet@708}  size = 3
  0 = "A2"
  1 = "A1"
  2 = "A3"
 1 = {HashSet@709}  size = 3
  0 = "A6"
  1 = "A5"
  2 = "A7"

I would like to have a new list like so:

list = A2,A1,A3, A6, A5, A7
Michael
  • 41,989
  • 11
  • 82
  • 128
OutOfMemoryError
  • 391
  • 2
  • 4
  • 16

3 Answers3

2

If you are only curious about not using iterator, you can use simple for each loop to solve the purpose

    List<Set<String>> hs = null ; // Actual given List<Set<String>
    ArrayList<String> arrayList = new ArrayList<String>(); // Plain List that will contain all the strings
    for(Set<String> set :hs) {
        arrayList.addAll(new ArrayList<String>(set)); // adding all the elements in list from hashset
    }

and with using streams(java 1.8 and above) in this way

    List<Set<String>> list = null ;
    List<String> al =  hs.stream().flatMap(Set::stream).collect(Collectors.toList());

but can you please explain why you don't want to use iterators?

Ravi
  • 719
  • 8
  • 23
1

You can't. Ordinarily, the only way to copy n things is to iterate over each of them.

The only way to avoid iterating over elements would be a lower-level operation like an array copy.

An ArrayList would do this (others like LinkedList would not) but no Set implementation in the JDK provides its own toArray implementation. They all use AbstractCollection.toArray which internally iterates over all of the elements.

If you implemented or found an array-based Set implementation (which would almost certainly not be an optimal Set, however) then you could flatten an ArrayList<ArraySet<String>> by using a series of array copies without iterating over the elements.

Michael
  • 41,989
  • 11
  • 82
  • 128
1

If you are using java 1.8 and above, then you can use streams but it will still use an internal iterator. Here is an example:

List<String> list = mainList.stream() // create stream
    .flatMap(Set::stream)             // convert Set<String> to Stream
    .collect(Collectors.toList());    // collect to new ArrayList
Aniket Sahrawat
  • 12,410
  • 3
  • 41
  • 67
  • "Without iterating over elements" – Michael Apr 02 '19 at 11:18
  • @Michael Atleast the answer is better than saying *You can't.* – Aniket Sahrawat Apr 02 '19 at 11:20
  • [No it isn't](https://meta.stackoverflow.com/questions/261168/is-this-is-not-possible-an-acceptable-answer). It's perfectly valid. If not iterating over the elements is a requirement, my answer is correct. If it's not a requirement, this question is a duplicate and should be closed. – Michael Apr 02 '19 at 11:21
  • 1
    @Michael I agree it's a valid answer, but arguing with JDK internals is relying on implementation details, which I don't think you should need to care about and might depend on and theoretically change between versions. – daniu Apr 02 '19 at 11:31
  • @daniu You could make the opposite point about this answer. I don't "know" that a stream iterates the elements. You could say that too is an implementation detail. Maybe the stream really doesn't iterate elements under the hood. Maybe it does some fancy JVM magic... – Michael Apr 02 '19 at 11:37
  • @Michael I meant to say I'd interpret the question as "without iterating _myself_", ie in user code. Ie I'd agree with your "duplicate" suggestion, but since your answer has been selected as correct, I guess that's what he was looking for. – daniu Apr 02 '19 at 11:40
  • 1
    @daniu Actually, my solution was selected as correct at first. But michael commented on the question and changed his mind. OutOfMemoryError asked me to write an answer, so I did. Anyways, nevermind :) – Aniket Sahrawat Apr 02 '19 at 11:42