Collect Java8 IntStream into Deque interface - collections

How to collect Java8 IntStream into Deque interface?
I can perform this kind of operation with List like that:
List<Integer> integerList = IntStream.of(1, 2, 3)
.boxed()
.collect(Collectors.toList());

You can't collect to an interface, but to an implementation of it (as long as it is a Collection) via Collectors.toCollection
Deque<Integer> d = IntStream.of(1, 2)
.boxed()
.collect(Collectors.toCollection(ArrayDeque::new));

use Collectors.toCollection to specify the collection you want, example:
.collect(Collectors.toCollection(ArrayDeque::new));
or any other implementation of the Deque interface.

Related

How to use method reference in Java 8 for Map merge?

I have following 2 forms of calling a collect operation, both return same result, but I still cannot depend fully on method references and need a lambda.
<R> R collect(Supplier<R> supplier,
BiConsumer<R,? super T> accumulator,
BiConsumer<R,R> combiner)
For this consider the following stream consisting on 100 random numbers
List<Double> dataList = new Random().doubles().limit(100).boxed()
.collect(Collectors.toList());
1) Following example uses pure lambdas
Map<Boolean, Integer> partition = dataList.stream()
.collect(() -> new ConcurrentHashMap<Boolean, Integer>(),
(map, x) ->
{
map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, (map, map2) ->
{
map2.putAll(map);
});
2) Following tries to use method references but 2nd argument still requires a lambda
Map<Boolean, Integer> partition2 = dataList.stream()
.collect(ConcurrentHashMap<Boolean, Integer>::new,
(map, x) ->
{
map.merge(x < 0.5 ? Boolean.TRUE : Boolean.FALSE, 1, Integer::sum);
}, Map::putAll);
How can I rewrite 2nd argument of collect method in java 8 to use method reference instead of a lambda for this example?
System.out.println(partition.toString());
System.out.println(partition2.toString());
{false=55, true=45}
{false=55, true=45}
A method reference is a handy tool if you have an existing method doing exactly the intended thing. If you need adaptations or additional operations, there is no special syntax for method references to support that, except, when you consider lambda expressions to be that syntax.
Of course, you can create a new method in your class doing the desired thing and create a method reference to it and that’s the right way to go when the complexity of the code raises, as then, it will get a meaningful name and become testable. But for simple code snippets, you can use lambda expressions, which are just a simpler syntax for the same result. Technically, there is no difference, except that the compiler generated method holding the lambda expression body will be marked as “synthetic”.
In your example, you can’t even use Map::putAll as merge function, as that would overwrite all existing mappings of the first map instead of merging the values.
A correct implementation would look like
Map<Boolean, Integer> partition2 = dataList.stream()
.collect(HashMap::new,
(map, x) -> map.merge(x < 0.5, 1, Integer::sum),
(m1, m2) -> m2.forEach((k, v) -> m1.merge(k, v, Integer::sum)));
but you don’t need to implement it by yourself. There are appropriate built-in collectors already offered in the Collectors class:
Map<Boolean, Long> partition2 = dataList.stream()
.collect(Collectors.partitioningBy(x -> x < 0.5, Collectors.counting()));

How to filter a vector of custom structs?

I am trying to filter a Vec<Vocabulary> where Vocabulary is a custom struct, which itself contains a struct VocabularyMetadata and a Vec<Word>:
#[derive(Serialize, Deserialize)]
pub struct Vocabulary {
pub metadata: VocabularyMetadata,
pub words: Vec<Word>
}
This is for handling a route in a web application, where the route looks like this: /word/<vocabulary_id>/<word_id>.
Here is my current code trying to filter the Vec<Vocabulary>:
let the_vocabulary: Vec<Vocabulary> = vocabulary_context.vocabularies.iter()
.filter(|voc| voc.metadata.identifier == vocabulary_id)
.collect::<Vec<Vocabulary>>();
This does not work. The error I get is:
the trait `std::iter::FromIterator<&app_structs::Vocabulary>` is not implemented for `std::vec::Vec<app_structs::Vocabulary>` [E0277]
I don't know how to implement any FromIterator, nor why that would be necessary. In another route in the same web app, same file I do the following, which works:
let result: Vec<String> = vocabulary_context.vocabularies.iter()
.filter(|voc| voc.metadata.identifier.as_str().contains(vocabulary_id))
.map(encode_to_string)
.collect::<Vec<String>>();
result.join("\n\n") // returning
So it seems that String implements FromIterator.
However, I don't get, why I cannot simple get back the Elements of the Vec from the filter or collect method.
How can I filter my Vec and simply get the elements of the Vec<Vocabulary>, for which the condition is true?
It's very important programming skill to learn how to create a minimal, reproducible example. Your problem can be reduced to this:
struct Vocabulary;
fn main() {
let numbers = vec![Vocabulary];
let other_numbers: Vec<Vocabulary> = numbers.iter().collect();
}
Let's look at the error message for your case:
error[E0277]: a collection of type `std::vec::Vec<Vocabulary>` cannot be built from an iterator over elements of type `&Vocabulary`
--> src/main.rs:5:57
|
5 | let other_numbers: Vec<Vocabulary> = numbers.iter().collect();
| ^^^^^^^ a collection of type `std::vec::Vec<Vocabulary>` cannot be built from `std::iter::Iterator<Item=&Vocabulary>`
|
= help: the trait `std::iter::FromIterator<&Vocabulary>` is not implemented for `std::vec::Vec<Vocabulary>`
This says that a Vec<Vocabulary> cannot be built from an iterator of &Vocabulary. Do you see the difference? You have an iterator of references (&), not an iterator of values. How would Vec know how to convert your references into values?
How do you fix it? I don't know what works best in your situation:
Don't iterate over references, iterate over the values themselves. The default choice requires that you have ownership of the vector. Use into_iter instead of iter:
let the_vocabulary: Vec<Vocabulary> = vocabulary_context
.vocabularies
.into_iter()
.filter(|voc| voc.metadata.identifier == vocabulary_id)
.collect();
You could also drain the iterator if you have a mutable reference:
let the_vocabulary: Vec<Vocabulary> = vocabulary_context
.vocabularies
.drain(..)
.filter(|voc| voc.metadata.identifier == vocabulary_id)
.collect();
Duplicate the objects by cloning them. This requires that the type you are iterating on implements Clone. If you pair this with filtering, you should call cloned() after filtering and before calling collect() to avoid cloning something you discard.
let the_vocabulary: Vec<Vocabulary> = vocabulary_context
.vocabularies
.iter()
.filter(|voc| voc.metadata.identifier == vocabulary_id)
.cloned()
.collect();
Don't collect values, collect a Vec of references. This requires that however you use the items afterwards can take an item by reference instead of by value:
let the_vocabulary: Vec<&Vocabulary> = vocabulary_context
.vocabularies
.iter()
.filter(|voc| voc.metadata.identifier == vocabulary_id)
.collect();
Note that I removed the redundant type specifiers (the turbofish ::<> on collect). You only need to specify the type of the variable or on collect, not both. In fact, all three examples could start with let the_vocabulary: Vec<_> to let the compiler infer the type inside the collection based on the iterator. This is the idiomatic style but I've kept the explicit types for demonstration purposes.
See also:
What is the difference between iter and into_iter?
When should I use `drain` vs `into_iter`?

Iterate over the sorted elements in a collection in tuples

I am trying to iterate over the sorted elements in a collection in tuples of 2 or more.
If I had a Vec, I could call
for window in my_vec.windows(2) {
// do something with window
}
but Vecs aren't implicitly sorted, which would be really nice to have. I tried to use a BTreeSet instead of a Vec, but I don't seem to be able to call windows on it.
When trying to call
for window in tree_set.iter().windows(2) {
// do something with window
}
I get the error
no method named `windows` found for type `std::collections::btree_set::Iter<'_, Card>` in the current scope
Itertools provides the tuple_windows method:
extern crate itertools;
use itertools::Itertools;
use std::collections::BTreeSet;
fn main() {
let items: BTreeSet<_> = vec![1, 3, 2].into_iter().collect();
for (a, b) in items.iter().tuple_windows() {
println!("{} < {}", a, b);
}
}
Note that windows is a method on slices, not on iterators, and it returns an iterator of subslices of the original slice. A BTreeMap presumably cannot provide that same iterator interface because it isn't built on top of a contiguous hunk of data; there's going to be some value that isn't immediately next in memory to the subsequent value.

Check if a type implements an interface in Julia

How to check that a type implements an interface in Julia?
For exemple iteration interface is implemented by the functions start, next, done.
I need is to have a specialization of a function depending on wether the argument type implements a given interface or not.
EDIT
Here is an example of what I would like to do.
Consider the following code:
a = [7,8,9]
f = 1.0
s = Set()
push!(s,30)
push!(s,40)
function getsummary(obj)
println("Object of type ", typeof(obj))
end
function getsummary{T<:AbstractArray}(obj::T)
println("Iterable Object starting with ", next(obj, start(obj))[1])
end
getsummary(a)
getsummary(f)
getsummary(s)
The output is:
Iterable Object starting with 7
Object of type Float64
Object of type Set{Any}
Which is what we would expect since Set is not an AbstractArray. But clearly my second method only requires the type T to implement the iteration interface.
my issue isn't only related to the iteration interface but to all interfaces defined by a set of functions.
EDIT-2
I think my question is related to
https://github.com/JuliaLang/julia/issues/5
Since we could have imagined something like T<:Iterable
Typically, this is done with traits. See Traits.jl for one implementation; a similar approach is used in Base to dispatch on Base.iteratorsize, Base.linearindexing, etc. For instance, this is how Base implements collect using the iteratorsize trait:
"""
collect(element_type, collection)
Return an `Array` with the given element type of all items in a collection or iterable.
The result has the same shape and number of dimensions as `collection`.
"""
collect{T}(::Type{T}, itr) = _collect(T, itr, iteratorsize(itr))
_collect{T}(::Type{T}, itr, isz::HasLength) = copy!(Array{T,1}(Int(length(itr)::Integer)), itr)
_collect{T}(::Type{T}, itr, isz::HasShape) = copy!(similar(Array{T}, indices(itr)), itr)
function _collect{T}(::Type{T}, itr, isz::SizeUnknown)
a = Array{T,1}(0)
for x in itr
push!(a,x)
end
return a
end
See also Mauro Werder's talk on traits.
I would define a iterability(::T) trait as follows:
immutable Iterable end
immutable NotIterable end
iterability(T) =
if method_exists(length, (T,)) || !isa(Base.iteratorsize(T), Base.HasLength)
Iterable()
else
NotIterable()
end
which seems to work:
julia> iterability(Set)
Iterable()
julia> iterability(Number)
Iterable()
julia> iterability(Symbol)
NotIterable()
you can check whether a type implements an interface via methodswith as follows:
foo(a_type::Type, an_interface::Symbol) = an_interface ∈ [i.name for i in methodswith(a_type, true)]
julia> foo(EachLine, :done)
true
but I don't quite understand the dynamic dispatch approach you mentioned in the comment, what does the generic function looks like? what's the input & output of the function? I guess you want something like this?
function foo(a_type::Type, an_interface::Symbol)
# assume bar baz are predefined
if an_interface ∈ [i.name for i in methodswith(a_type, true)]
# call function bar
else
# call function baz
end
end
or some metaprogramming stuff to generate those functions respectively at compile time?

Efficient conversion from String[] to F# List

I'm coming to F# from a C# background and a little behind on the different lists and collections. I recently ran into a case where I needed to go from a string[] to 'T list. I ended up using list comprehension to do the cast:
let lines = File.ReadAllLines(#"C:\LinesOText.txt") // returns a string array
let listOLines = [for l in lines -> l] // use list comprehension to get the f# list
Is there a more efficient way of doing the conversion?
Use List.ofArray or Array.toList.
this should do it:
let lines = File.ReadAllLines(#"C:\LinesOText.txt") |> List.ofArray
Here's another way to do it:
let listOfLines = [yield! File.ReadAllLines(#"C:\LinesOText.txt")]

Resources