This question already has answers here:
How can I turn a List of Lists into a List in Java 8?
(12 answers)
Closed 5 years ago.
I would like to map each entry in my list by calling expand(), which returns multiple entries, and then collect the result as a list.
Without streams, I would accomplish this like:
List<String> myList = new ArrayList<>();
List<String> expanded = new ArrayList<>();
for (String s : myList) {
expanded.addAll(expand(s));
}
return expanded;
private List<String> expand(String x) {
return Arrays.asList(x, x, x);
}
How can I accomplish this with streams? This gives a compilation error:
return myList.stream().map(this::expand).collect(Collectors.toList());
flatMap should help you :
return myList.stream()
.flatMap(x -> expand(x).stream())
.collect(Collectors.toList());
return myList.stream().map(this::expand).collect(Collectors.toList());
returns List<List<String>> because myList.stream().map(this::expand) returns a stream typed as Stream<List<String>> as you pass to map() a variable declared List<String> variable and not String.
You don't want that.
So chain Stream.map() with Stream.flatMap() to amalgamate Stream<List<String>> to Stream<String> :
return myList.stream()
.map(this::expand)
.flatMap(x->x.stream())
.collect(Collectors.toList());
use flatMap to convert the Stream<List<String> to a Stream<String>:
return myList.stream().map(this::expand).flatMap(Collection::stream).collect(Collectors.toList());
Related
This question already has answers here:
How to add prefix to all the elements of List efficiently?
(2 answers)
Closed 2 years ago.
I need to append a prefix "ROLE_" to each string collected after mapping with string in an object. I have done this in two steps as showin in method mappedListWithPrefix:
class MyClass {
String uid;
}
////////
List<String> mappedListWithPrefix(List<MyClass> list) {
List<String> op = list.stream().map(MyClass::getUid).collect(Collectors.toList());//step 1
op.replaceAll(s -> "ROLE_"+s);//step 2
return op;
}
Is there a way to do this in a single step, without using a second list, somewhat like map( "ROLE_"+MyClass::getUid) ? (Pls note this is just to convey idea, this mapping wont wrk)
You can either add a second map step:
List<String> op = list.stream()
.map(MyClass::getUid)
.map(s -> "ROLE_" + s)
.collect(Collectors.toList());
or just do both operations in one map call:
List<String> op = list.stream()
.map(o -> "ROLE_" + o.getUid())
.collect(Collectors.toList());
Which one to pick is mostly down to personal preference.
This question already has answers here:
Every combination of 2 strings in List Java 8 [duplicate]
(1 answer)
Should I use Java 8 Streams Api to combine two Collections?
(2 answers)
Closed 2 years ago.
I have two Lists:
List<Object1> listOne = provider.getObjects().stream().collect(Collectors.toList());
List<Object2> listTwo = provider2.getObjects().stream().collect(Collectors.toList());
Now I want create List containg all possible Object1-Object2 combinations: List<ObjectCombinations> result;
class ObjectCombinations {
Object1 object1;
Object2 object2;
public ObjectCombinations(Object1 object1, Object2 object2) {
this.object1 = object1;
this.object2 = object2;
}
}
How is that possible with java 8 streams?
You can use flatMap to get all the combinations:
List<ObjectCombinations> result =
listOne.stream()
.flatMap(o1 -> listTwo.stream()
.map(o2 -> new ObjectCombinations(o1,o2)))
.collect(Collectors.toList());
First you create a Stream<Object1>, then you use flatMap to combine each element of that stream with all the elements of listTwo, and create the ObjectCombinations instances, which you collect to a List.
You can use flatMap where you can stream over 2nd list and create ObjectCombinations and flatten the list.
List<ObjectCombinations> res =
listOne.stream()
.flatMap(a -> listTwo.stream().map(b -> new ObjectCombinations(a,b)))
.collect(Collectors.toList());
This question already has answers here:
Convert List of List into list in java
(5 answers)
Closed 5 years ago.
I have a multimap Map<T,List<L>> map and I need a list with all the values of the values from the map, namely List<L>. With map.values() I get a List<List<L>>, but thats not what I want.
Does someone know a clean solution without looping?
If you are using Java 8, you could collect all L values from all List<L>s in a single List<L> by Stream#flatMap:
final List<L> list = map
// get a Collection<List<L>>
.values()
// make a stream from the collection
.stream()
// turn each List<L> into a Stream<L> and merge these streams
.flatMap(List::stream)
// accumulate the result into a List
.collect(Collectors.toList());
Otherwise, a for-each approach with Collection#addAll can be applied:
final List<L> list = new ArrayList<>();
for (final List<L> values : map.values()) {
list.addAll(values);
}
This question already has answers here:
Using Java 8's Optional with Stream::flatMap
(12 answers)
Closed 6 years ago.
Is there a more elegant way of practically achieving this in Java 8?
list.stream()
.map(e -> myclass.returnsOptional(e))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
I'm talking about filter(Optional::isPresent) followed by map(Optional::get), I want to elegantly collect in a list only Optional results which have a value.
In your case you can use one flatMap instead of combinations of map filter and again map.
To Do that it's better to define a separate function for creating a Stream: public private static Stream<Integer> createStream(String e) to not have several lines of code in lambda expression.
Please see my full Demo example:
public class Demo{
public static void main(String[] args) {
List<String> list = Arrays.asList("1", "2", "Hi Stack!", "not", "5");
List<Integer> newList = list.stream()
.flatMap(Demo::createStream)
.collect(Collectors.toList());
System.out.println(newList);
}
public static Stream<Integer> createStream(String e) {
Optional<Integer> opt = MyClass.returnsOptional(e);
return opt.isPresent() ? Stream.of(opt.get()) : Stream.empty();
}
}
class MyClass {
public static Optional<Integer> returnsOptional(String e) {
try {
return Optional.of(Integer.valueOf(e));
} catch (NumberFormatException ex) {
return Optional.empty();
}
}
}
in case returnsOptional cannot be static you will need to use "arrow" expression instead of "method reference"
Not sure if its so different but you could just filter based on your optional instead of getting the optional and filtering next.
Something like this?
list.stream()
.filter(e -> myclass.returnsOptional(e).isPresent())
.collect(Collectors.toList());
Note: This will only work if returnsOptional returns the same object type as your original list item types.
This question already has an answer here:
Can I transform a Stream<List<X>> to a Stream<X>? [duplicate]
(1 answer)
Closed 6 years ago.
I have a hashmap that looks something like this:
Map<String, ImageRecipeMap> contentIdToImageIdsMap = new HashMap<>();
my ImageRecipeMap object looks something like this:
public class ImageRecipeMap {
private ContentType contentType;
private List<String> imageIds;
public List<String> getImageIds() {
return imageIds;
}
public void setImageIds(List<String> imageIds) {
this.imageIds = imageIds;
}
...
}
I want to grab all the Lists of imageIds and create a total imageIds list using java 8 streams. This is what I have so far, but I seem to have a compile error on my collect:
List<String> total = contentIdToImageIdsMap.values().stream()
.map(value -> value.getImageIds())
.collect(Collectors.toList());
Your solution returns List<List<String>>. Use .flatMap() to flatten them like this.
List<String> total = contentIdToImageIdsMap.values().stream()
.flatMap(value -> value.getImageIds().stream())
.collect(Collectors.toList());
.flatMap() changes Stream<List<String>> to Stream<String>.