You can use the Streams API :
List<Object> multiFieldsList =
multiFieldMap.entrySet()
.stream()
.flatMap(e -> e.getValue()
.stream()
.map(o -> queryService.query(e.getKey(), queryService.property("id").eq(o))))
.collect(Collectors.toList());
Answer from Eran on Stack OverflowYou can use the Streams API :
List<Object> multiFieldsList =
multiFieldMap.entrySet()
.stream()
.flatMap(e -> e.getValue()
.stream()
.map(o -> queryService.query(e.getKey(), queryService.property("id").eq(o))))
.collect(Collectors.toList());
You can indeed use a stream to simplify you inner loop.
You can replace:
List<Object> ids = entry.getValue();
for (Object id : ids) {
Object entity = queryService.query(entityName, queryService.property("id").eq(id));
multiFieldsList.add(entity);
}
with:
entry.getValue().map(
id -> queryService.query(entityName, queryService.property("id").eq(id))
).forEach(multiFieldsList::add);
But you don't really gain much from that. Your choice...
See @Eran's answer for a "full stream" solution.
The function Function<? super T,? extends R> mapper of the map method basically represents any function taking one parameter and returning a value so in this specific case the lambda p -> new Student(p.getId(), p.getName()) is a function taking a Person p and returning a Student hence fits into that perfectly.
To look at it another way, the lambda is equivalent to:
.map(new Function<Person, Student>() {
@Override
public Student apply(Person p) {
return new Student(p.getId(), p.getName());
}
})
You can write like this Function<Person,Student> function = p -> new Student(p.getId(), p.getName())
so as you see it is represent a function.
personList.stream().filter(p -> p.getPersonType().equals("student"))
.map(function::apply) // p -> function.apply(p)
.collect(Collectors.toList());
If you want to initialize a Map in a single statement, you can use Collectors.toMap.
Imagine you want to build a Map<Integer, Boolean> mapping an integer to the result of calling some function f:
private static final Map<Integer,Boolean> MAP =
Collections.unmodifiableMap(IntStream.range(0, 1000)
.boxed()
.collect(Collectors.toMap(i -> i, i -> f(i))));
private static final boolean f(int i) {
return Math.random() * 100 > i;
}
If you want to initialize it with "static" known values, like the example in your answer, you can abuse the Stream API like this:
private static final Map<Integer, Boolean> MAP =
Stream.of(new Object[] { 1, false }, new Object[] { 2, true })
.collect(Collectors.toMap(s -> (int) s[0], s -> (boolean) s[1]));
Note that this is a real abuse and I personally would never use it: if you want to construct a Map with known static values, there is nothing to gain from using Streams and you would be better off to use a static initializer.
Here is how to implement a field initializer in Java 8 in a single statement using a lambda.
private static final Map<Integer,Boolean> map =
((Supplier<Map<Integer,Boolean>>)() -> {
Map<Integer,Boolean> mutableMap = new HashMap<>();
mutableMap.put( 1, false );
mutableMap.put( 2, true );
return Collections.unmodifiableMap( mutableMap );
}).get();
Java 9 solution:
private static final Map<Integer,Boolean> map = Map.of( 1, false, 2, true );
and if you have more than 10 entries, Map.of() won't work, so you need this:
private static final Map<Integer,Boolean> map = Map.ofEntries(
Map.entry( 1, false ),
Map.entry( 2, true ),
Map.entry( 3, false ),
Map.entry( 4, true ),
Map.entry( 5, false ),
Map.entry( 6, true ),
Map.entry( 7, false ),
Map.entry( 8, true ),
Map.entry( 9, false ),
Map.entry( 10, true ),
Map.entry( 11, false ) );