Just make sure array has unique titles and then use Collectors.toMap
Map<String, List<String>> result = Arrays.stream(myStringArray)
.map(title -> new AbstractMap.SimpleEntry<>(title,
pages.stream().filter(page -> isPageContainsTitle(page,title)).collect(Collectors.toList())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
And as @Naman suggested you can avoid the intermediate map operation
Map<String, List<String>> result = Arrays.stream(myStringArray)
.collect(Collectors.toMap(Function.identity()
,title -> pages.stream()
.filter(page -> isPageContainsTitle(page, title))
.collect(Collectors.toList())));
Answer from Ryuzaki L on Stack OverflowCreate list of object from another using Java 8 Streams - Stack Overflow
java - Convert a List of objects to a Map using Streams - Stack Overflow
Need help with creating a map from a list with stream
java stream List<Object[]> to Map<Object, List<Object[]>> - Stack Overflow
Just make sure array has unique titles and then use Collectors.toMap
Map<String, List<String>> result = Arrays.stream(myStringArray)
.map(title -> new AbstractMap.SimpleEntry<>(title,
pages.stream().filter(page -> isPageContainsTitle(page,title)).collect(Collectors.toList())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
And as @Naman suggested you can avoid the intermediate map operation
Map<String, List<String>> result = Arrays.stream(myStringArray)
.collect(Collectors.toMap(Function.identity()
,title -> pages.stream()
.filter(page -> isPageContainsTitle(page, title))
.collect(Collectors.toList())));
Below code should work for you:
package com.shree.test;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamTest {
public static void main(String[] args) {
String[] myStringArray = {"TITLE1", "TITLE2", "TITLE3"};
List<String> pages = new ArrayList<>();
pages.add("TEXT,TITLE2,TEXT,ONE,TWO");
pages.add("TEXT,TITLE1,TEXT,ONE,TWO");
pages.add("TEXT,TITLE2,TEXT,ONE,TWO");
pages.add("TEXT,TITLE2,TEXT,TITLE3,TWO");
pages.add("TEXT,TITLE3,TEXT,ONE,TWO");
Map<Object, Object> titleMap = getTitleMap(myStringArray, pages);
titleMap.entrySet().forEach(System.out::println);
}
private static Map<Object, Object> getTitleMap(String[] myStringArray, List<String> pages) {
Map<Object, Object> titleMap = Arrays.asList(myStringArray).stream()
.map(
(title)->{
return new AbstractMap.SimpleEntry<>(title, pages.stream()
.filter((page)->page.contains(title))
.collect(Collectors.toList()));
}
)
.collect(Collectors.toMap(entry->entry.getKey(), entry->entry.getValue()));
return titleMap;
}
}
If you want to iterate over a list and create a new list with "transformed" objects, you should use the map() function of stream + collect(). In the following example I find all people with the last name "l1" and each person I'm "mapping" to a new Employee instance.
public class Test {
public static void main(String[] args) {
List<Person> persons = Arrays.asList(
new Person("e1", "l1"),
new Person("e2", "l1"),
new Person("e3", "l2"),
new Person("e4", "l2")
);
List<Employee> employees = persons.stream()
.filter(p -> p.getLastName().equals("l1"))
.map(p -> new Employee(p.getName(), p.getLastName(), 1000))
.collect(Collectors.toList());
System.out.println(employees);
}
}
class Person {
private String name;
private String lastName;
public Person(String name, String lastName) {
this.name = name;
this.lastName = lastName;
}
// Getter & Setter
}
class Employee extends Person {
private double salary;
public Employee(String name, String lastName, double salary) {
super(name, lastName);
this.salary = salary;
}
// Getter & Setter
}
What you are possibly looking for is map(). You can "convert" the objects in a stream to another by mapping this way:
...
.map(userMeal -> new UserMealExceed(...))
...
Map< String, Set<String>> map = list.stream()
.collect(
Collectors.groupingBy(
A::getFirstName, Collectors.mapping(
A::getLastName, Collectors.toSet())));
You were on the right track you need to use:
Collectors.groupingByto group by thefirstName.And then use a downstream collector like
Collectors.mapppingas a second parameter ofCollectors.groupingByto map to thelastName.And then finally collect that in a
Set<String>by invokingCollectors.toSet:
You never told the collector to extract last names.
I suppose you need something like
list.stream
.collect(groupingBy(
A::getFirstName, // The key is extracted.
mapping( // Map the stream of grouped values.
A::getLastName, // Extract last names.
toSet() // Collect them into a set.
)));
I have a list of objects (let's say object has string a, string b, string c ) need to convert it into map with key as a+b and value as entire object. Is this possible? Please help.
I m trying like this syntax: list.stream().collect(Collectors.toMap(key, value)); But not able to set key value as concatenation of a and b.
It seems you need to group by element at index zero of an array Object
Collectors.groupingBy groups by the key
Map<Object, List<Object[]>> map = objects.stream()
.collect(Collectors.groupingBy(o -> o[0]));
with null and empty checks
Map<Object, List<Object[]>> map = objects.stream()
.filter(o -> o != null && o.length != 0)
.collect(Collectors.groupingBy(o -> o[0]));
Example
List<Object[]> objects = new ArrayList<>();
objects.add(new Object[] { 0, 1, 2, 3, 4, 5 });
objects.add(new Object[] { 1, 1, 2, 3, 4, 5 });
objects.add(new Object[] { 2, 1, 2, 3, 4, 5 });
objects.add(new Object[] { 0, 6, 7, 8, 9 });
Map<Object, List<Object[]>> map = objects.stream()
.collect(Collectors.groupingBy(o -> o[0]));
System.out.println(map);
output is like
{
0 = [[Ljava.lang.Object;@378bf509,
[Ljava.lang.Object;@5fd0d5ae],
1 = [[Ljava.lang.Object;@2d98a335],
2 = [[Ljava.lang.Object;@16b98e56]
}
you can see 0 has two List<Object[]> values grouped by
I would make the whole procedure more explicit and clean. Using a mixed-style with lots of comments and good variable names.
This should help a lot when it comes down to reading, understanding and maintaining your code.
Map<Object, List<Object[]>> convert(List<Object[]> entities) {
Map<Object, List<Object[]>> idToEntitesWithSameId = new HashMap<>();
entities.forEach(entity -> {
// Create an entry for each entity,
// merge with entities of same id
Object id = entity[0];
// Get current value or empty list
List<Object[]> entitiesWithId = idToEntitesWithSameId
.computeIfAbsent(id, ArrayList::new);
// Add own entity, merge with other
// entities of same id
Arrays.stream(entity).forEach(entitiesWithId::add);
});
return idToEntitesWithSameId;
}
yourTypes.stream()
.collect(Collectors.groupingBy(
ObjectA::getType,
Collectors.mapping(
ObjectA::getId, Collectors.toList()
)))
Employee list to map
List<Employee> list = new ArrayList<>();
list.add(new Employee(1, "John",80000));
list.add(new Employee(2, "Jack", 90000));
list.add(new Employee(3, "Ricky", 120000));
// key = id, value - name
Map<Integer, String> result1 = list.stream().collect(
Collectors.toMap(Employee::getId, Employee::getName));
listOfData.stream()
.flatMap(e -> e.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
update:
Slightly different variant to user1692342's answer for completeness.
list.stream()
.map(e -> Arrays.asList(e.get("Role"), e.get("Name")))
.collect(Collectors.groupingBy(e -> e.get(0),
Collectors.mapping(e -> e.get(1), Collectors.toList())));
Based on the idea given by Aomine:
list.stream()
.map(e -> new AbstractMap.SimpleEntry<>(e.get("Role"), e.get("Name")))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())));