Java Stream Collectors sort the given stream [duplicate] - java-8

This question already has answers here:
How is this HashSet producing sorted output?
(5 answers)
Closed 2 years ago.
can you please let me know why below code returns the set sorted order given an unsorted array?
Stream<Integer> s = Stream.of(2, 3, 1, 4, 5);
Set<Integer> mySet = s.collect(Collectors.toSet());
System.out.println(mySet);
O/p
1, 2, 3, 4, 5
This doesn't happen if I use List instead of Set.
Also the sorting is not always correct when there are negative numbers in the input.
Is there any inbuilt functionality to sort the Set?

This is just an accident and has nothing to do with Collector or Stream. On OpenJDK 11.0.2, I'm getting this (as Collector.toSet() is currently backed by HashSet):
Set<Integer> set = new HashSet<>();
set.add(2);
set.add(3);
set.add(1);
set.add(4);
set.add(5);
System.out.println(set); // [1, 2, 3, 4, 5]
But try this:
set.add(100);
System.out.println(set); // [1, 2, 3, 4, 100, 5]
It is really just an accident. A very curious one, indeed, which has to do with the Integer.hashCode() implementation (it's just the Integer.intValue() itself), and how this results in accidentally ordering HashSet elements for certain sets.

It is just a coincidence. The Set interface does not provide any ordering guarantees, but LinkedHashSet.

Related

Find exact value overlap between two arrays [duplicate]

This question already has answers here:
Ruby - array intersection (with duplicates)
(7 answers)
Closed 1 year ago.
I have two arrays
a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]
I want to return the values that appear in both arrays AND the exact amount that they appear
# => [1, 1, 3, 3]
I can't use a1 & a2 because that will return unique values ([1, 3])
What's the best way to achieve this?
It looks like what you have there are not really arrays, they are multisets or bags.
There is a general rule in programming: if you choose your data representation right, your algorithms become simpler.
So, if you use multisets instead of arrays, your problem will become trivial, since what you are looking for is literally just the intersection of two multisets.
Unfortunately, there is no multiset implementation in the core or standard libraries, but there are a couple of multiset gems available on the web. For example, there is the multimap gem, which also includes a multiset. Unfortunately, it needs a little bit of love and care, since it uses a C extension that only works until YARV 2.2. There is also the multiset gem.
require 'multiset'
m1 = Multiset.new(a1)
#=> #<Multiset:#3 1, #1 2, #3 3>
m2 = Multiset.new(a2)
#=> #<Multiset:#2 1, #2 3, #2 5>
m = m1 & m2
#=> #<Multiset:#2 1, #2 3>
Personally, I am not too big a fan of the inspect output, but we can see what's going on and that the result is correct: m contains 2 × 1 and 2 × 3.
If you really need the result as an Array, you can use Multiset#to_a:
m.to_a
#=> [1, 1, 3, 3]
At first I do get the intersection between a1 and a2 with (a1 & a2). After that I iterate over the intersection and check which array has a lower count of each element. The element gets than added to the result array as many times as it occurs in the array with the lower count using result.fill
a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]
result = []
(a1 & a2).each do |e|
a1.count(e) < a2.count(e) ? result.fill(e, result.size, a1.count(e)) : result.fill(e, result.size, a2.count(e))
end
pp result

How do you sort a list with a comparison function where values for a & b are known ahead of time?

I'm writing a simple interpreter that people can use (among other things) to sort a list via a comparison function (preferably a stable sort). Sorting algorithms that I'm familiar with all seem to require a variable number of calls to that comparison function and you don't know ahead of time which items will be compared to each other. That won't work because of the nature of what work is done in the interpreted language vs the runtime at what times.
The steps required by the interpreter are:
Step 1: Create a list of as to be compared to another list of bs, one a & b at a time. Something like sort([1, 2, 3]) producing:
a = [2, 3]
b = [1, 2]
(2 is compared to 1 and then 3 is compared to 2 in the above example, going index by index.)
Step 2: Create two new lists (before and after) with the same number of items as a and b to represent the result of the comparison function. The values are any null or non-null value. Something like:
before = [2, 3]
after = [null, null]
(2 should come before 1, representing 1 from b as null. The non-null values are preserved, but any non-null value could be in 2's place.)
I can impose a limitation that the values in before and after must be items from the lists a and b, but I'd prefer not to if I possibly can. I mention it because I'm unsure how I could know where the non-null value came from (a or b). But if the items compared from a and b are the same but only one is null at the end, I have the same problem.
Step 3: Use those two lists before and after to sort the original list. Something like:
sort([1, 2, 3], greaterThan) => [3, 2, 1]
// a = [2, 3]
// b = [1, 2]
// before = [2, 3]
// after = [null, null]
(If both values are non-null or both null, it should favor their original order relative to each other, or a "stable" sort.)
In such a trivial example, the items in a and b are sufficient to sort the list. The Javascript (the language the interpreter is written in) Array.sort method will compare them like this:
(2, 1)
(3, 2)
and be done. But if the order of the original list were [2, 3, 1] then it has to do:
(3, 2)
(1, 3)
(1, 2)
(1, 3)
(I don't know why or what algorithm they use).
In that example, I would have to provide lists a and b as [3, 1, 1, 1] and [2, 3, 2, 3] respectively.
How do I get a list for a and b that will work given any comparison function or order of the original list -- and then use the resulting before and after lists to sort that original list?

Non-mutating sorted list in Dart

I can sort a list like this in Dart:
final myList = [6, 3, 7, 1, 0, 2];
myList.sort();
However, this is a destructive sort since it mutates it in place. I'd like to do something like this:
final myList = [6, 3, 7, 1, 0, 2];
final newList = myList.sorted();
where my list stays the same but newList contains the sorted list. Dart apparently doesn't have this functionality, so how do I implement that myself?
In searching for the answer to this question my main struggle was knowing the proper way to copy a list, which wasn't as obvious as it seems like it should be. I found the answer to that, so I am also posting an answer to my original question below, Q&A style.
You can create a new sorted list without affecting the original list like so:
final myList = [6, 3, 7, 1, 0, 2];
final sorted = myList.toList()..sort();
Calling toList() copies the list. The .. is to get a reference to the list itself since sort() is a void function. This gives the same result:
final sorted = myList.toList();
sorted.sort();
Printing the values of both lists gives the following results:
print(myList); // [6, 3, 7, 1, 0, 2]
print(sorted); // [0, 1, 2, 3, 6, 7]
You can read more about copying lists here.
I'd suggest you to create a fixed-length list.
final myList = [6, 3, 7, 1, 0, 2];
final sortedList = myList.toList(growable: false)..sort();
It seems to me that this question is really "How can I copy a List?", and the sorting aspect is tangential.
There are multiple ways to copy an Iterable to a new List:
Using a method on the original Iterable: iterable.toList()
Using a List constructor: List.of(iterable)
Using the spread operator in a List literal: [...iterable]. Note that this always creates a growable List.
Note that List.from should not be used since that uses dynamic types and loses type information. Effective Dart prefers .toList().
Also note that the above applies to Sets too (iterable.toSet(), {...iterable}, Set.of(iterable)).

Ruby Combinations based on Value [duplicate]

This question already has answers here:
Iterate Array and add each consecutive array value
(2 answers)
Closed 7 years ago.
I'm trying to figure out a way to use Ruby's combination method to return combinations whos sum equals a certain amount. I may not be familiar enough with Ruby or understand if I can add any lambda expressions essentially to the combinations result, is there a way to do what I want with the combination method or is it very limited? Like can you add extra criteria around the combinations result based on some criteria?
combination returns an Enumerator, which you can then filter to get only the combinations you want.
Take this example:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].combination(2).
select { |n| n.reduce(:+) == 8 } # => [[1, 7], [2, 6], [3, 5]]

Genetic algorithm, cross over without duplicate data

I'm creating a genetic algorithm and I just encounter a problem, let's take an example. I have a list of numbers : [2, 3, 6, 8, 9, 1, 4] which represent my datas.
The best solution to my problem depends on the order of the numbers in the list. So I have two solution : S1 [2, 3, 9, 8, 1, 6, 4] and S2 [1, 6, 4, 3, 9, 2, 8]
If I do a basic cross-over with S1 and S2 I may obtain a solution like this : child [2, 3, 9, 8, 9, 2, 8] and we can see that the solution is bad because I duplicate datas.
The question is how may I realized an evolution (so cross-over) without duplicate thoses datas ?
thanks.
You will need a crossover operator like Ordered Crossover (OX1) that can perform crossover without duplicate thoses datas:
OX1:
A randomly selected portion of one parent is mapped to a portion
of the other parent. From the replaced portion on, the rest is filled
up by the remaining genes, where already present genes are omitted and
the order is preserved.
You should take care with mutation too, because it can change the genes order, in this case you can use a mutation operator like Reverse Sequence Mutation (RSM).
In the reverse sequence mutation operator, we take a sequence S
limited by two positions i and j randomly chosen, such that i<j.
The gene order in this sequence will be reversed by the same way as
what has been covered in the previous operation.
You have Permutation Encoding, look at this explanation: http://www.obitko.com/tutorials/genetic-algorithms/crossover-mutation.php
In general you take the elements of the first parent in order in which they are met in the first parent and you take the rest of the elements in the order in which they are met in the second parent.

Resources