If I have a List<List<Foo>> I can use flat map to flatten the list.
But I have by MyClass which has a List<Foo> and the Foo class has list of bars List<Bar> then I have to do something like this :
myClass.getFoos().stream().map(Foo::getBars).forEach({
bar -> // some code
});
Is it possible to use flat map in this scenario so I can get list of bars from MyClass in one shot.
Try this:
myClass.getFoos().stream()
.map(Foo::getBars)
.flatMap(List::stream) // flatten the lists
.forEach(...);
Note the exlcusive use of method references, which I find neater and easier to read than lambdas.
myClass.getFoos()
.stream()
.flatMap(x -> x.getBars().stream())
.forEach(...)
Related
I have a list of class R with list of other class P
List<R> rList = getRListFromDb();
I would like to get the all the P objects in another list
List<P> result = new ArrayList<>();
I tried these, but giving me Class cast exception, saying class P cannot be converted to class R. By the way I have seen issue given below, but tried and could not figure it out.
How can I turn a List of Lists into a List in Java 8?
1. rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
2. rList.forEach(r -> result.addAll(r.getP()));
I would like to what is incorrect here and also would like to know different ways of getting this done in Java 8.
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
would work if you didn't use flatMap (since addAll requires a Collection, but flatMap transforms your Stream<List<P>> to a Stream<P>.
This would work:
rList.stream().map(R::getP).forEach(result::addAll);
With flatMap it should be:
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::add);
That said, the correct way is to use collect:
List<P> result = rList.stream()
.map(R::getP)
.flatMap(List::stream)
.collect(Collectors.toList());
or
List<P> result = rList.stream()
.flatMap(r -> r.getP().stream())
.collect(Collectors.toList());
I am trying to convert a Map to another Map where the new key is simply the original key toString(). With the streams API I do this as follows:
mapMap.entrySet().stream().collect(Collectors.toMap(
(Map.Entry entry) -> entry.getKey().toString(),
(Map.Entry entry) -> entry.getValue()
));
The problem is that this doesn't preserve the internal Map type. I don't mind returning a TreeMap if the original map happens to be a HashMap, but the other way around is a problematic as sorting of the elements is removed. I've been fooling around with variations of the above code to get this done, but I don't seem to get very far. Right now, I have written it without streams, as follows:
TreeMap<String, Integer> stringMap = new TreeMap<>();
for (OriginalType t: originalMap.keySet()) {
stringMap.put(t.toString(), originalMap.get(t));
}
Can anyone put me in the right direction to do this with streams?
Thanks
There is an overload of Collectors.toMap which will allow you to specify which type of map you want returned.
mapMap.entrySet().stream().collect(Collectors.toMap(
(Map.Entry entry) -> entry.getKey().toString(),
(Map.Entry entry) -> entry.getValue(),
(val1, val2) -> { throw new RuntimeException("Not expecting duplicate keys"); },
() -> new TreeMap<>()
));
(A note about the third argument: it is intended as a function which will merge two values together that have the same key. When I don't expect these things to happen, I prefer to throw an exception.)
I've started using Kotlin as a substitute for java and quite like it. However, I've been unable to find a solution to this without jumping back into java-land:
I have an Iterable<SomeObject> and need to convert it to a list so I can iterate through it more than once. This is an obvious application of an immutable list, as all I need to do is read it several times. How do I actually put that data in the list at the beginning though? (I know it's an interface, but I've been unable to find an implementation of it in documentation)
Possible (if unsatisfactory) solutions:
val valueList = arrayListOf(values)
// iterate through valuelist
or
fun copyIterableToList(values: Iterable<SomeObject>) : List<SomeObject> {
var outList = ArrayList<SomeObject>()
for (value in values) {
outList.add(value)
}
return outList
}
Unless I'm misunderstanding, these end up with MutableLists, which works but feels like a workaround. Is there a similar immutableListOf(Iterable<SomeObject>) method that will instantiate an immutable list object?
In Kotlin, List<T> is a read-only list interface, it has no functions for changing the content, unlike MutableList<T>.
In general, List<T> implementation may be a mutable list (e.g. ArrayList<T>), but if you pass it as a List<T>, no mutating functions will be exposed without casting. Such a list reference is called read-only, stating that the list is not meant to be changed. This is immutability through interfaces which was chosen as the approach to immutability for Kotlin stdlib.
Closer to the question, toList() extension function for Iterable<T> in stdlib will fit: it returns read-only List<T>.
Example:
val iterable: Iterable<Int> = listOf(1, 2, 3)
val list: List<Int> = iterable.toList()
What is the terminology for the usage of "new" in:
list.Add(new{a=1, b=2})
And what type should I replace the T in List getList if I want to use the list as the returned value? I don't want to replace T with "object" because I want to parse it in Linq query.
Thanks.
Since you did not specify a type: new {1), it's called object initializers with anonymous types. (MSDN Explaining them) The Object Initializer part is where you do { a=1, b=2}.
If you want to be able to reference a type, you will have to create a type and stuff the values in.
list.Add(
new MyType() {
a=1,
b=2
});
If you are just going to be pairing two items look into using the Pair Class. There is also a Triplet Class just in case you might want to store 3 items.
I have a ptr_vector list of my own objects. Something like this:
boost::ptr_vector<SomeClass> *list;
list->push_back(new SomeClass()>;
...
BOOST_FOREACH(SomeClass *tempObj, list) // [x]
{
tempObj->...
}
>‘boost::ptr_vector<SomeClass>*’ is not a class, struct, or union type
I think your problem is that you declared 'list' as a pointer to a boost::ptr_vector and are trying to use it as an automatic object.
IMHO the first line of your code snippet should read:
boost::ptr_vector<SomeClass> list;