I would like to transform list into map using as key values only two string values. Then as values just list of strings containing elements from odd or even index positions from input list. Here is old fashion code:
JavaScript
x
Map<String, List<String>> map = new HashMap<>();
List<String> list = Arrays.asList("one", "two", "three", "four");
map.put("evenIndex", new ArrayList<>());
map.put("oddIndex", new ArrayList<>());
for (int i = 0; i < list.size(); i++) {
if(i % 2 == 0)
map.get("evenIndex").add(list.get(i));
else
map.get("oddIndex").add(list.get(i));
}
How to transform this code into Java 8 using streams to get this result?
JavaScript
{evenIndex=[one, three], oddIndex=[two, four]}
My current messy attempt require modifying elements of list, but definitly must be better option.
JavaScript
List<String> listModified = Arrays.asList("++one", "two", "++three", "four");
map = listModified.stream()
.collect(Collectors.groupingBy(
str -> str.startsWith("++") ? "evenIndex" : "oddIndex"));
Or maybe someone help me with this incorrect solution?
JavaScript
IntStream.range(0, list.size())
.boxed()
.collect(Collectors.groupingBy( i -> i % 2 == 0 ? "even" : "odd",
Collectors.toMap( (i -> i ) , i -> list.get(i) ) )));
which return this:
JavaScript
{even={0=one, 2=three}, odd={1=two, 3=four}}
Advertisement
Answer
You were on the right track with streaming over the indexes:
JavaScript
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
IntStream.range(0,list.size())
.boxed()
.collect(groupingBy(
i -> i % 2 == 0 ? "even" : "odd",
mapping(list::get, toList())
));
If you are ok with having your map be indexed by a boolean
you can use partitioningBy
:
JavaScript
IntStream.range(0, list.size())
.boxed()
.collect(partitioningBy(
i -> i % 2 == 0,
mapping(list::get, toList())
));