2

I want to convert this while loop to equivalent code using a Java 8 Streams, but I don't know how to both stream the List and remove elements from it.

private List<String> nameList = new ArrayList<>();

while (nameList.size() > 0) {
    String nameListFirstEntry = nameList.get(0);
    nameList.remove(0);
    setNameCombinations(nameListFirstEntry);
}
8
  • 2
    Convert it to what? SQL? COBOL? Pascal? Commented Apr 11, 2017 at 12:16
  • This is already valid Java8 code (although I don't know what it does and why it does it). Commented Apr 11, 2017 at 12:17
  • In java-8 stream or foreach Commented Apr 11, 2017 at 12:18
  • what is your code trying to do? what is setNameCombinations? Commented Apr 11, 2017 at 12:19
  • Neither streams nor forEach are allowed to modify the source list, so you're out of luck on failthful conversion. Commented Apr 11, 2017 at 12:20

2 Answers 2

6

I guess this will do

nameList.forEach(this::setNameCombinations);
nameList.clear();

In case you don't need the original list anymore, you might as well create a new empty list instead.

Sign up to request clarification or add additional context in comments.

7 Comments

Doesn't fullfill the requirement stream the list and remove elements from it.
ok, iterating AND deletion are two seperate concerns, I wonder why both have to be satisfied in the same stream? the actual question was "convert while loop to equivalent code using stream api", and there you go. You never asked for doing it in the same stream ... which I doubt being a sensible requirement anyway (though I have to admit Bohemian's approach is quite interessting)
You're right, but the question also says but I don't know how to both stream the list and remove elements from it.
Yes, agreed. His solution is clever and perfectly fulfills the requirement. The requirements (contraints) are nonsense nonetheless. It's one of those theoretical examples where you think "nice to know, but never do this in practice" ;)
@Gerald You're correct that a stream shouldn't modify the source, but that's not what's going on in my code. The stream in my answer does not modify the source. The supplier does, which is completely different. The stream code is deterministic and obeys guidelines. The supplier code is simple and could even have used a method reference, but the code is briefer as is.
|
4

Because List#remove(int) also returns the element, you can both stream the list's elements and remove them via a stream:

Stream.generate(() -> nameList.remove(0))
    .limit(nameList.size())
    .forEach(this::setNameCombinations);

This code doesn't break any "rules". From the javadoc of Stream#generate():

Returns an infinite sequential unordered stream where each element is generated by the provided Supplier. This is suitable for generating constant streams, streams of random elements, etc.

There is no mention of any restrictions on how the supplier is implemented or that is must have no side effects etc. The Supplier's only contract is to supply.


For those who doubt this is "works", here's some test code using 100K elements showing that indeed order is preserved:

int size = 100000;
List<Integer> list0 = new ArrayList<>(size); // the reference list
IntStream.range(0, size).boxed().forEach(list0::add);
List<Integer> list1 = new ArrayList<>(list0); // will feed stream
List<Integer> list2 = new ArrayList<>(size);  // will consume stream

Stream.generate(() -> list1.remove(0))
        .limit(list1.size())
        .forEach(list2::add);

System.out.println(list0.equals(list2)); // always true

18 Comments

@Eugene So don't add parallel(). It is not "illegal", or even mysterious. It is using List#remove() as the stream's Supplier... big deal. Try it yourself if you have doubts.
@eugene Let's get something straight here: This code does not stream the list, and the stream is not modifying anything. The Supplier is mutating something as it supplies, but the stream doesn't know or care how the Supplier supplies. There is nothing here that breaks any guidelines or contracts.
@Eugene why do you believe that adding parallel should get the same result? Where does it say that? I can tell you that adding parallel usually does change the result - that is the encounter order of the elements of the stream becomes non-deterministic, if the particular stream supports parallelism (the stream if a List for example does not).
assuming the nameList is made out of 3 elements [a,b,c]; by the same result Im expecting to see these 3 elements in any order (since it's parallel)
@M.Prokhorov it does not matter.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.