Does collect return a list snapshot if run on a parallel stream?











up vote
2
down vote

favorite
1












I have a unit test that started to fail on Circle CI only. It fails on the last line in this (Kotlin) example:



generator.generateNames(50) // returns List<String>
.parallelStream()
.map { name ->
val playerId = "${name.firstName.toLowerCase()}"
Player(playerId = playerId)
}.collect(Collectors.toList()).last()


throwing: Caused by: java.util.NoSuchElementException.



It works always on my local machine or on Circle CI if I do not use a parallel stream. My theory is that the collect call returns a List snapshot (it actually doesn't block until the List is completely filled) and that CI doesn't have enough CPU to collect a single element in other threads?



However, my stream is ordered and so is the Collector right? Is this even collecting in parallel?










share|improve this question






















  • Does the returned list definitely contain an element? .last() will throw NoSuchElementException if it is empty
    – Eamon Scullion
    2 days ago










  • Yes. Like I said running the code unchanged on my dev machine always work. On CI it works if I turn the parallel stream into a sequential one.
    – reikje
    2 days ago






  • 2




    Not very sure of what Kotlin does, but if making things sequential seems to be the only solution currently. Then I would suggest trying to collect(Collectors.toList()) as Player list and break the part of fetching the last into two steps. Something like this in java : List<Player> playerList = generator.generateNames(50) // returns List<String> .parallelStream() .map(name -> new Player(name.getFirstName.toLowerCase()) }.collect(Collectors.toList()); Player lastplayer = playerList.get(playerList.size()-1); .. note that this shouldn't work either on Circle CI for your code.
    – nullpointer
    2 days ago








  • 3




    I don’t understand, in which regard “Circle CI” is relevant in this operation at all. The only thing that doesn’t look standard Java or trivial operation, is generator.generateNames(50). If this method returns one of the standard List implementations, there should be no problem. But perhaps, it returns some kind of lazy list implementation that is not thread safe?
    – Holger
    2 days ago












  • What flavour and version of a JDK are you using on both machines?
    – Jayson Minard
    2 days ago















up vote
2
down vote

favorite
1












I have a unit test that started to fail on Circle CI only. It fails on the last line in this (Kotlin) example:



generator.generateNames(50) // returns List<String>
.parallelStream()
.map { name ->
val playerId = "${name.firstName.toLowerCase()}"
Player(playerId = playerId)
}.collect(Collectors.toList()).last()


throwing: Caused by: java.util.NoSuchElementException.



It works always on my local machine or on Circle CI if I do not use a parallel stream. My theory is that the collect call returns a List snapshot (it actually doesn't block until the List is completely filled) and that CI doesn't have enough CPU to collect a single element in other threads?



However, my stream is ordered and so is the Collector right? Is this even collecting in parallel?










share|improve this question






















  • Does the returned list definitely contain an element? .last() will throw NoSuchElementException if it is empty
    – Eamon Scullion
    2 days ago










  • Yes. Like I said running the code unchanged on my dev machine always work. On CI it works if I turn the parallel stream into a sequential one.
    – reikje
    2 days ago






  • 2




    Not very sure of what Kotlin does, but if making things sequential seems to be the only solution currently. Then I would suggest trying to collect(Collectors.toList()) as Player list and break the part of fetching the last into two steps. Something like this in java : List<Player> playerList = generator.generateNames(50) // returns List<String> .parallelStream() .map(name -> new Player(name.getFirstName.toLowerCase()) }.collect(Collectors.toList()); Player lastplayer = playerList.get(playerList.size()-1); .. note that this shouldn't work either on Circle CI for your code.
    – nullpointer
    2 days ago








  • 3




    I don’t understand, in which regard “Circle CI” is relevant in this operation at all. The only thing that doesn’t look standard Java or trivial operation, is generator.generateNames(50). If this method returns one of the standard List implementations, there should be no problem. But perhaps, it returns some kind of lazy list implementation that is not thread safe?
    – Holger
    2 days ago












  • What flavour and version of a JDK are you using on both machines?
    – Jayson Minard
    2 days ago













up vote
2
down vote

favorite
1









up vote
2
down vote

favorite
1






1





I have a unit test that started to fail on Circle CI only. It fails on the last line in this (Kotlin) example:



generator.generateNames(50) // returns List<String>
.parallelStream()
.map { name ->
val playerId = "${name.firstName.toLowerCase()}"
Player(playerId = playerId)
}.collect(Collectors.toList()).last()


throwing: Caused by: java.util.NoSuchElementException.



It works always on my local machine or on Circle CI if I do not use a parallel stream. My theory is that the collect call returns a List snapshot (it actually doesn't block until the List is completely filled) and that CI doesn't have enough CPU to collect a single element in other threads?



However, my stream is ordered and so is the Collector right? Is this even collecting in parallel?










share|improve this question













I have a unit test that started to fail on Circle CI only. It fails on the last line in this (Kotlin) example:



generator.generateNames(50) // returns List<String>
.parallelStream()
.map { name ->
val playerId = "${name.firstName.toLowerCase()}"
Player(playerId = playerId)
}.collect(Collectors.toList()).last()


throwing: Caused by: java.util.NoSuchElementException.



It works always on my local machine or on Circle CI if I do not use a parallel stream. My theory is that the collect call returns a List snapshot (it actually doesn't block until the List is completely filled) and that CI doesn't have enough CPU to collect a single element in other threads?



However, my stream is ordered and so is the Collector right? Is this even collecting in parallel?







kotlin java-8 java-stream






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 2 days ago









reikje

1,11711325




1,11711325












  • Does the returned list definitely contain an element? .last() will throw NoSuchElementException if it is empty
    – Eamon Scullion
    2 days ago










  • Yes. Like I said running the code unchanged on my dev machine always work. On CI it works if I turn the parallel stream into a sequential one.
    – reikje
    2 days ago






  • 2




    Not very sure of what Kotlin does, but if making things sequential seems to be the only solution currently. Then I would suggest trying to collect(Collectors.toList()) as Player list and break the part of fetching the last into two steps. Something like this in java : List<Player> playerList = generator.generateNames(50) // returns List<String> .parallelStream() .map(name -> new Player(name.getFirstName.toLowerCase()) }.collect(Collectors.toList()); Player lastplayer = playerList.get(playerList.size()-1); .. note that this shouldn't work either on Circle CI for your code.
    – nullpointer
    2 days ago








  • 3




    I don’t understand, in which regard “Circle CI” is relevant in this operation at all. The only thing that doesn’t look standard Java or trivial operation, is generator.generateNames(50). If this method returns one of the standard List implementations, there should be no problem. But perhaps, it returns some kind of lazy list implementation that is not thread safe?
    – Holger
    2 days ago












  • What flavour and version of a JDK are you using on both machines?
    – Jayson Minard
    2 days ago


















  • Does the returned list definitely contain an element? .last() will throw NoSuchElementException if it is empty
    – Eamon Scullion
    2 days ago










  • Yes. Like I said running the code unchanged on my dev machine always work. On CI it works if I turn the parallel stream into a sequential one.
    – reikje
    2 days ago






  • 2




    Not very sure of what Kotlin does, but if making things sequential seems to be the only solution currently. Then I would suggest trying to collect(Collectors.toList()) as Player list and break the part of fetching the last into two steps. Something like this in java : List<Player> playerList = generator.generateNames(50) // returns List<String> .parallelStream() .map(name -> new Player(name.getFirstName.toLowerCase()) }.collect(Collectors.toList()); Player lastplayer = playerList.get(playerList.size()-1); .. note that this shouldn't work either on Circle CI for your code.
    – nullpointer
    2 days ago








  • 3




    I don’t understand, in which regard “Circle CI” is relevant in this operation at all. The only thing that doesn’t look standard Java or trivial operation, is generator.generateNames(50). If this method returns one of the standard List implementations, there should be no problem. But perhaps, it returns some kind of lazy list implementation that is not thread safe?
    – Holger
    2 days ago












  • What flavour and version of a JDK are you using on both machines?
    – Jayson Minard
    2 days ago
















Does the returned list definitely contain an element? .last() will throw NoSuchElementException if it is empty
– Eamon Scullion
2 days ago




Does the returned list definitely contain an element? .last() will throw NoSuchElementException if it is empty
– Eamon Scullion
2 days ago












Yes. Like I said running the code unchanged on my dev machine always work. On CI it works if I turn the parallel stream into a sequential one.
– reikje
2 days ago




Yes. Like I said running the code unchanged on my dev machine always work. On CI it works if I turn the parallel stream into a sequential one.
– reikje
2 days ago




2




2




Not very sure of what Kotlin does, but if making things sequential seems to be the only solution currently. Then I would suggest trying to collect(Collectors.toList()) as Player list and break the part of fetching the last into two steps. Something like this in java : List<Player> playerList = generator.generateNames(50) // returns List<String> .parallelStream() .map(name -> new Player(name.getFirstName.toLowerCase()) }.collect(Collectors.toList()); Player lastplayer = playerList.get(playerList.size()-1); .. note that this shouldn't work either on Circle CI for your code.
– nullpointer
2 days ago






Not very sure of what Kotlin does, but if making things sequential seems to be the only solution currently. Then I would suggest trying to collect(Collectors.toList()) as Player list and break the part of fetching the last into two steps. Something like this in java : List<Player> playerList = generator.generateNames(50) // returns List<String> .parallelStream() .map(name -> new Player(name.getFirstName.toLowerCase()) }.collect(Collectors.toList()); Player lastplayer = playerList.get(playerList.size()-1); .. note that this shouldn't work either on Circle CI for your code.
– nullpointer
2 days ago






3




3




I don’t understand, in which regard “Circle CI” is relevant in this operation at all. The only thing that doesn’t look standard Java or trivial operation, is generator.generateNames(50). If this method returns one of the standard List implementations, there should be no problem. But perhaps, it returns some kind of lazy list implementation that is not thread safe?
– Holger
2 days ago






I don’t understand, in which regard “Circle CI” is relevant in this operation at all. The only thing that doesn’t look standard Java or trivial operation, is generator.generateNames(50). If this method returns one of the standard List implementations, there should be no problem. But perhaps, it returns some kind of lazy list implementation that is not thread safe?
– Holger
2 days ago














What flavour and version of a JDK are you using on both machines?
– Jayson Minard
2 days ago




What flavour and version of a JDK are you using on both machines?
– Jayson Minard
2 days ago












1 Answer
1






active

oldest

votes

















up vote
3
down vote



accepted










The exception you are getting probably has a message in it, and not just the name of the exception. That message is likely telling you the error. For example, the last part of your code calls the Kotlin extension function last() which in the implementation:



public fun <T> List<T>.last(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[lastIndex]
}


So if you are seeing "List is empty" message in the stack trace for java.util.NoSuchElementException then that is the cause.



Also, if you share the stack trace you can actually see what is throwing the exception. But looking at your code this is the only likely candidate.



The question then is, "why is the final list empty?!" ... is generateNames(50) working differently in this environment? The problem is not with collect(Collectors.toList()) which provides a synchronous result.






share|improve this answer



















  • 1




    After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
    – reikje
    2 days ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53373038%2fdoes-collect-return-a-list-snapshot-if-run-on-a-parallel-stream%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
3
down vote



accepted










The exception you are getting probably has a message in it, and not just the name of the exception. That message is likely telling you the error. For example, the last part of your code calls the Kotlin extension function last() which in the implementation:



public fun <T> List<T>.last(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[lastIndex]
}


So if you are seeing "List is empty" message in the stack trace for java.util.NoSuchElementException then that is the cause.



Also, if you share the stack trace you can actually see what is throwing the exception. But looking at your code this is the only likely candidate.



The question then is, "why is the final list empty?!" ... is generateNames(50) working differently in this environment? The problem is not with collect(Collectors.toList()) which provides a synchronous result.






share|improve this answer



















  • 1




    After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
    – reikje
    2 days ago















up vote
3
down vote



accepted










The exception you are getting probably has a message in it, and not just the name of the exception. That message is likely telling you the error. For example, the last part of your code calls the Kotlin extension function last() which in the implementation:



public fun <T> List<T>.last(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[lastIndex]
}


So if you are seeing "List is empty" message in the stack trace for java.util.NoSuchElementException then that is the cause.



Also, if you share the stack trace you can actually see what is throwing the exception. But looking at your code this is the only likely candidate.



The question then is, "why is the final list empty?!" ... is generateNames(50) working differently in this environment? The problem is not with collect(Collectors.toList()) which provides a synchronous result.






share|improve this answer



















  • 1




    After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
    – reikje
    2 days ago













up vote
3
down vote



accepted







up vote
3
down vote



accepted






The exception you are getting probably has a message in it, and not just the name of the exception. That message is likely telling you the error. For example, the last part of your code calls the Kotlin extension function last() which in the implementation:



public fun <T> List<T>.last(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[lastIndex]
}


So if you are seeing "List is empty" message in the stack trace for java.util.NoSuchElementException then that is the cause.



Also, if you share the stack trace you can actually see what is throwing the exception. But looking at your code this is the only likely candidate.



The question then is, "why is the final list empty?!" ... is generateNames(50) working differently in this environment? The problem is not with collect(Collectors.toList()) which provides a synchronous result.






share|improve this answer














The exception you are getting probably has a message in it, and not just the name of the exception. That message is likely telling you the error. For example, the last part of your code calls the Kotlin extension function last() which in the implementation:



public fun <T> List<T>.last(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[lastIndex]
}


So if you are seeing "List is empty" message in the stack trace for java.util.NoSuchElementException then that is the cause.



Also, if you share the stack trace you can actually see what is throwing the exception. But looking at your code this is the only likely candidate.



The question then is, "why is the final list empty?!" ... is generateNames(50) working differently in this environment? The problem is not with collect(Collectors.toList()) which provides a synchronous result.







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 days ago

























answered 2 days ago









Jayson Minard

35.7k13103170




35.7k13103170








  • 1




    After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
    – reikje
    2 days ago














  • 1




    After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
    – reikje
    2 days ago








1




1




After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
– reikje
2 days ago




After some investigation, it turned out that running a parallel stream exhausted a JedisPool. I excluded that line above because I thought it would be not relevant. It was a bit unfortunate that the exhausted pool also came back with a NoSuchElementException. That got me to the wrong track. But basically you answered my question: when collect(Collectors.toList()) returns, the List is always fully populated - also when using parallel streams.
– reikje
2 days ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53373038%2fdoes-collect-return-a-list-snapshot-if-run-on-a-parallel-stream%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen