I'm trying to understand the behavior of parallelStream() in java 8. Here is my sample code.
List<Person> javaProgrammers = new ArrayList<Person>() {
{
add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000));
add(new Person("Tamsen", "Brittany", "Java programmer", "female", 33, 1500));
add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800));
add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600));
add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200));
add(new Person("Maude", "Jaimie", "Java programmer", "female", 33, 1900));
add(new Person("Shawn", "Randall", "Java programmer", "male", 33, 2300));
add(new Person("Jayden", "Corrina", "Java programmer", "female", 33, 1700));
add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000));
add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300));
}
};
System.out.println("Serial:" + javaProgrammers.stream().filter(person -> person.age == 33).findFirst().toString());
System.out.println("Parallel:" + javaProgrammers.parallelStream().filter(person -> person.age == 33).findFirst().toString());
Here I'm comparing stream() and parallelStream(), and I expect Brittany Tamsen to be return always in stream() call because that's the first match. But for parallelStream() I do not expect Brittany Tamsen to be returned always because it can be one of any matches, as I expect it to run in parallel.
But the problem is that it also returns Brittany Tamsen always. So it doesn't look like it runs in parallel.
Am I missing something here?
In addition to Bohemian's answer, It's important to add that, yes, findFirst() will return the first element matching the predicate, whether the stream is parallel or not, since the stream has an encounter order in this case (being created from a List).
findAny(), on the contrary, is free to return any element matching the predicate (and should thus be preferred if you don't really care about which matching element is returned, since it might allow returning sooner in case of a parallel stream).
There is a whole paragraph on ordering in the package documentation and another one the interaction between concurrency and ordering further down.
Excerpt (reading the rest is highly recommended):
Streams may or may not have a defined encounter order. Whether or not
a stream has an encounter order depends on the source and the
intermediate operations. Certain stream sources (such as List or
arrays) are intrinsically ordered
The findFirst documentation itself then refers to the encounter order concept defined above.
Returns an Optional describing the first element of this stream, or an
empty Optional if the stream is empty. If the stream has no encounter
order, then any element may be returned.
The Spliterator and Collector docs also describe some behavior relevant to ordering for more complex uses of parallel streams.
Related
I have an array
arrayOf<Any>("Apple",46,"287",574,"Peach","3","69",78,"Grape","423") and I need to sort it: firstly numbers suppose to go like "3",46,"69"... and then words by alphabet... So I am trying first to divide them on separate arrays by type and then some manipulation. Do you have advice of how to solve this problem?
Here's a concise* approach:
val a = arrayOf<Any>("Apple", 46, "287", 574, "Peach", "3", "69", 78, "Grape", "423")
val (numbers, nonNumbers) = a.partition{ it.toString().toIntOrNull() != null }
val result = (numbers.sortedBy{ it.toString().toInt() }
+ nonNumbers.sortedBy{ it.toString() })
println(result) // [3, 46, 69, 78, 287, 423, 574, Apple, Grape, Peach]
This uses partition() to split the array into two lists: one holding all the numbers, and one holding the rest. (To handle all possible types, it calls toString(), and then determines whether that string would be a valid integer.)
Then it sorts the first sublist (holding numbers) according to their integer value, and the second sublist lexicographically; finally, it uses + to join the sorted sublists into one.
This will work for elements of all possible types, not just String and Int. (However, although it's not clear from the output, the result preserves the original types; the string and integer conversions are only done temporarily for the purposes of sorting.)
Note that it produces a list, not an array. (It will also operate on a list or other collection.) Lists are much better supported in the standard library, can be resized, have a decent toString() implementation, come in mutable and immutable versions, have countless implementations with different characteristics, work better with generics, and several other advantages. Arrays are mainly for interoperability with old code, and a few specific uses (varargs, low-level implementation, and the main() method); for everything else, lists are much preferable.
(However, if you really need an array result, you can call result.toTypedArray().)
* While it's fun to puzzle out the shortest solution, that doesn't necessarily make it the best…
In practice, the best code is clear, simple, easy to read and maintain; conciseness can help that, or it can go too far, and this answer might go slightly too far. (In fact, I've tweaked it since first posted, naming the sublists in the hope of making it a little more readable.)
This is also less efficient than some other answers, as it creates lots of temporary objects (four lists and many strings). In many cases, that may not matter — but it's worth being aware of.
In any event, it's always worth being aware of alternatives, and so I hope this is instructive!
You can sort the array using a custom comparator:
fun main() {
println(
arrayOf<Any>("Apple",46,"287",574,"Peach","3","69",78,"Grape","423")
.sortedWith(
compareBy<Any> {
it is String && it.toLongOrNull() == null
} then compareBy {
when {
it is Number -> it.toLong()
it is String && it.toLongOrNull() != null -> it.toLong()
else -> it.toString()
}
}
)
)
}
Output: [3, 46, 69, 78, 287, 423, 574, Apple, Grape, Peach]
You can try my solution
val a = arrayOf<Any>("Apple",46,"287",574,"Peach","3","69",78,"Grape","423")
val numbers = mutableListOf<Any>()
val strings = mutableListOf<String>()
for(e in a){
if(e is Int) numbers.add(e)
if(e is String){
if(e.toIntOrNull() == null){
strings.add(e)
} else {
numbers.add(e)
}
}
}
val result = numbers.also { value -> value.sortBy{it.toString().toInt()} } + strings.sorted()
println(result) // [3, 46, 69, 78, 287, 423, 574, Apple, Grape, Peach]
So just had to make some manipulation
val onlyNumbers = a.filterIsInstance<Int>()
val allStrings = a.filterIsInstance<String>().sorted()
val onlyStrings = mutableListOf<String>()
val listOfEditedNumbers = mutableListOf<Int>()
allStrings.forEach {
try {
val toInt = it.toInt()
listOfEditedNumbers.add(toInt)
} catch (e: java.lang.Exception){
onlyStrings.add(it)
}
}
val allNumbers = onlyNumbers.toList() + listOfEditedNumbers
val finalSortedNumberList = allNumbers.sorted()
val finalNumbersList = mutableListOf<Any>()
finalSortedNumberList.forEach {
if (it in onlyNumbers) finalNumbersList.add(it)
if (allStrings.contains(it.toString())) finalNumbersList.add(it.toString())
}
val finalTotalList = finalNumbersList + onlyStrings.sorted()
My application periodically consumes data from an API:
[
{
"name": "A",
"val": 12
},
{
"name": "B",
"val": 22
},
{
"name": "C",
"val": 32
}
]
Its task is to perform some operations on this data, for example, to subtract the "A" value from its previous sample. So we always keep the current sample for further use.
The incoming data has two constraints:
In some iterations some parts of data may be missing, i.e. the "A" object may not be available in some JSONs,
The order of objects is not guaranteed to be consistent, i.e. in a JSON we may have A, B, C, and in another one, we may have "C", "A", "B" ...
The intuitive way to perform these operations is a linear search. We loop through the current JSON and for each object we search for the counterpart in the previous JSON. Then we perform the calculations and put them inside another JSON.
What is an efficient way to do this task? I preferably like to do this in Go but the language is not important.
I am trying to make a simple naive text adventure game (base one this page) to learn OCaml.
The game is about making an game engine, so all the information about rooms, items ect, is store in a json file.
Sample json file would be like this:
{
"rooms":
[
{
"id": "room1",
"description": "This is Room 1. There is an exit to the north.\nYou should drop the white hat here.",
"items": ["black hat"],
"points": 10,
"exits": [
{
"direction": "north",
"room": "room2"
}
],
"treasure": ["white hat"]
},
{
"id": "room2",
"description": "This is Room 2. There is an exit to the south.\nYou should drop the black hat here.",
"items": [],
"points": 10,
"exits": [
{
"direction": "south",
"room": "room1"
}
],
"treasure": ["black hat"]
}
],
"start_room": "room1",
"items":
[
{
"id": "black hat",
"description": "A black fedora",
"points": 100
},
{
"id": "white hat",
"description": "A white panama",
"points": 100
}
],
"start_items": ["white hat"]
}
I've almost done the game, but on the project description page, it says two of the objectives are
Design user-defined data types, especially records and variants.
Write code that uses pattern matching and higher-order functions on lists and on trees.
However, the only user-defined datatype I made is a record type used to capture the current state of the game, I did not use tree and variant :
type state = {
current_inventory : string list ;
current_room : string ;
current_score : int ;
current_turn : int ;
}
then just parse user input and use pattern matching to handle different situations.
I'm been trying to figure out how should I use variant (or polymorphic variant) and tree in my game.
Can anyone please provide some suggestions?
The json is inherently a tree. You may, of course just parse the json without having an in-memory representation and perform side-effectful computations as you descent though the json data to fill in hash tables with the data that you've read. This is a valid option, but it looks like that authors of the course expect, that you first read the entire json and represent it in memory as a tree, and then perform lookups on the tree.
What concerning variants, then you should represent with a variant type the following data:
movement directions: type dir = N | NE | E ...
verbs type verb = Go | Take of item | Drop of item
Also, it would be a good idea to create an abstract data types for room and items, that will guarantee that they are is actually present in the json data bases. You're using string to represent them. But this type includes all values, including those, that doesn't represent a valid identifiers, as well as those, that doesn't occur in the game description file. Inventory items are also deserve to get their own type.
In general in languages with rich type system, you should try to express as much as possible with the type system.
Just to be less theoretical, if I were you, then I will have the following types in my game (as a first approximation):
type game
type room
type item
type verb
type dir
type treasure
type state
(** a static representation of a game (using a tree inside) *)
module Game : sig
type t = game
val from_json : string -> t option
val start : t -> room
val room_exits : t -> room -> (dir * room) list
end
module Room : sig
type t = room
val description : t -> string
val items : t -> item list
val points : t -> int
val treasure : t -> treasure list
end
...
I thought I had it with rethinkdb :) but now I'm a bit confused -
for this query, counting grouped data:
groupedRql.count()
I'm getting the expected results (numbers):
[{"group": "a", "reduction": 41}, {"group": "b", "reduction": 39}...]
all reduction results are ~40 which is expected (and correct), but when I count using reduce like this:
groupedRql.map(function(row) {
return row.merge({
count: 0
})
}).reduce(function(left, right) {
return {count: left("count").add(1)}
})
I'm getting much lower results (~10) which MAKE NO SENSE:
[{"group": "a", "reduction": 10}, {"group": "b", "reduction": 9}...]
I need to use reduce, of course, for further manipulation.
Am I missing something?
I'm using v2.0.3 on server, queries tested directly on the dataexplorer.
The problem lay in here
return {count: left("count").add(1)}
It should be
return {count: left("count").add(right("count"))}
The reduce run paralel between multiple shards, multiple CPU core. When you do
return {count: left("count").add(1)}
you ignore some count from the right.
It's noted in this document: https://www.rethinkdb.com/docs/map-reduce/#how-gmr-queries-are-executed
it’s important to keep in mind that the reduce function is not called
on the elements of its input stream from left to right. It’s called on
either the elements of the stream in any order or on the output of
previous calls to the function.
Value edits at the bottom.
I would prefer a more robust solution. The following is a very hacky approach.
Suppose the following:
Redis.rpush("list_of_objs", ['{"value": 1, "id: 3}', '{"value": 2, "id": 9}',
'{"value": 8, "id": 1}', '{"value": 9, "id": 99}', '{"value": 10, "id": 1252}',
'{"value": 0, "id": 99999}']).
I now have a list of simple json objects that only have value and id attributes.
If you're curious,
Redis.lrange("list_of_objs", 0, -1)
#=> ['{"value": 1, "id: 3}', '{"value": 2, "id": 9}', '{"value": 8, "id": 1}', '{"value": 9, "id": 99}', '{"value": 10, "id": 1252}', '{"value": 0, "id": 99999}']
Awesome. Now, let us assume we want to delete '{"value": 8, "id": 1}'. That is achieved through the following command:
Redis.lrem("list_of_objs", 1, '{"value": 8, "id": 1}')
If you call Redis.lrange("list_of_objs", 0, -1) once more, you'll now see that we successfully deleted the element.
This works in some cases, but truth be told, in many cases, this isn't sufficient. I'm not guaranteed that what I want to delete will be exactly the same since when I put it into the list. Someone may choose to change '{"value": 8, "id": 1}' to '{"value": 22, "id": 1}' before I decide to delete it. However, if I try to delete it now, I'm screwed. The same command won't work. Now, if we used some Ruby logic, we could easily get this sorted, but the solution becomes rather hacky if you ask me.
Now, the assumption with this type of solution is that some element within your object, in our case the id, stays the same throughout the lifetime of the object.
Now, the solution:
Redis.multi do
array = Redis.lrange("list_of_objs", 0, -1)
index_of_element_to_be_destroyed = array.index { |el| JSON.parse(el)["id"] == 1 }
element = Redis.lindex("list_of_objs", index_of_element_to_be_destroyed)
Redis.lrem("list_of_objs", 1, element)
end
That seems a bit hacky to have to delete 1 element. I'm pretty sure by doing it in multi, I'm safe from the index potentially changing via something concurrent.
Edit 1: Actually, I'm pretty sure the above might not even work. I'm not sure if I am allowed to do such ruby like array.index in a Redis.multi block.
Edit 2: Perhaps I do the deletion in Ruby, then just re-rpush the array? I would like to avoid that.
Edit 3: This question seems to hold valuable information, but if I'm seriously expected to use a loop and watch, then I think this is much more hacky than I anticipated.
That being said, is there a better way to delete an element in a list based on some condition?