![](/img/trans.png)
[英]Convert Map<String,List<Person>> to Map<String,List<Employee>>, using Java 8 streams. I did this but how do this without for loop
[英]How do I convert a List<Employee> to Map<Employee, List<String>> using java8?
我有一份員工名單。
我已經覆蓋了 Employee 類的 equals 和 hashcode。 我想將員工列表轉換為以員工對象為鍵並以唯一車號列表為值的映射。
PS:列表中也可能有重復的鍵。 因此,我應該合並列表中存在的汽車編號的值並放入地圖中。
請在下面找到我嘗試使用迭代的代碼。 我想知道如何使用 java 8 來做到這一點。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TestMap {
public static void main(String[] args) {
Map<Employee, List<String>> map = new LinkedHashMap<>();
Employee e1 = new Employee("A", new ArrayList(Arrays.asList("car1", "car2", "car3")));
Employee e2 = new Employee("B", new ArrayList(Arrays.asList("car111", "car222", "car333")));
Employee e3 = new Employee("C", new ArrayList(Arrays.asList("car1111", "car2222", "car3333")));
Employee e4 = new Employee("A", new ArrayList(Arrays.asList("car2", "car3", "car4")));
List<Employee> employeeList = new ArrayList<>();
employeeList.add(e1);
employeeList.add(e2);
employeeList.add(e3);
employeeList.add(e4);
for (Employee employee : employeeList) {
if(map.containsKey(employee)) {
List<String> temp = map.get(employee);
temp.addAll(employee.getCars());
temp = temp.stream().distinct().collect(Collectors.toList());
map.put(employee, temp);
}
else {
List<String> values = new ArrayList<>();
values.addAll(employee.getCars().stream().distinct().collect(Collectors.toList()));
map.put(employee, values);
}
}
System.out.println("map::: "+ map);
}
}
class Employee {
private List<String> cars;
public Employee(String empName, List<String> cars) {
this.empName = empName;
this.cars = cars;
}
public List<String> getCars() {
return cars;
}
public void setCars(List<String> cars) {
this.cars = cars;
}
private String empName;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((empName == null) ? 0 : empName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (empName == null) {
if (other.empName != null)
return false;
} else if (!empName.equals(other.empName))
return false;
return true;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
}
我喜歡獲取一段命令式代碼並將其轉換為函數式......仍然Java流會產生如下丑陋的代碼......
Employee e1 = new Employee("A", Arrays.asList("car1", "car2", "car3"));
Employee e2 = new Employee("B", Arrays.asList("car111", "car222", "car333"));
Employee e3 = new Employee("C", Arrays.asList("car1111", "car2222", "car3333"));
Employee e4 = new Employee("A", Arrays.asList("car2", "car3", "car4"));
List<Employee> myList = Arrays.asList(e1, e2, e3, e4);
BinaryOperator<Employee> accumulator = (x, y) -> {
List<String> cars = Stream.concat(x.getCars().stream(), y.getCars().stream()).distinct()
.collect(Collectors.toList());
x.setCars(cars);
return x;
};
Map<Employee, List<String>> collect =
myList
.stream()
.collect(Collectors.groupingBy(x -> x))
.entrySet()
.stream()
.collect(
Collectors.toMap(
e -> e.getKey(),
e -> e.getValue()
.stream()
.reduce(accumulator)
.map(Employee::getCars)
.get())
);
System.out.println(collect);
它將打印:
{Employee [empName=A]=[car1, car2, car3, car4], Employee [empName=B]=[car111, car222, car333], Employee [empName=C]=[car1111, car2222, car3333]}
我不會這樣做,太丑了,太做作......
特別是如果你將它與像 Scala 這樣的原生函數式語言進行比較......
val emps: List[Employee] = List(
Employee("A", List("car1", "car2", "car3")),
Employee("B", List("car111", "car222", "car333")),
Employee("C", List("car1111", "car2222", "car3333")),
Employee("A", List("car2", "car3", "car4")))
val x = emps.groupBy(_.name)
.map{case (k,cs) => (k,cs.flatMap(_.cars).distinct) }
println(x)
}
case class Employee(name: String, cars: List[String])
// Map(A -> List(car1, car2, car3, car2, car3, car4), C -> List(car1111, car2222, car3333), B -> List(car111, car222, car333))
在 java 中,我會考慮使用vavr這樣做,這將導致以下代碼:
io.vavr.collection.List<Employee> emps = io.vavr.collection.List.of(
new Employee("A", Arrays.asList("car1", "car2", "car3")),
new Employee("B", Arrays.asList("car111", "car222", "car333")),
new Employee("C", Arrays.asList("car1111", "car2222", "car3333")),
new Employee("A",Arrays.asList("car2","car3","car4")));
io.vavr.collection.Map<String, io.vavr.collection.List<String>>
mapValues = emps.groupBy(emp->emp.getEmpName())
.mapValues( v ->v.flatMap(Employee::getCars).distinct());
System.out.println(mapValues);
在 Vavr 代碼和 scala 中,我使用 Employee 名稱而不是對象作為鍵,因為它看起來很合適,無法選擇一個員工實例而不是另一個,所以我使用了鍵。
可以簡單地通過使用Set
而不是List
來解決:
Map<Employee, Set<String>> collect = employeeList.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.flatMapping(employee -> employee.getCars().stream(), Collectors.toSet())));
輸出:
{Employee{name='A'}=[car2, car3, car1, car4], Employee{name='B'}=[car333, car222, car111], Employee{name='C'}=[car1111, car2222, car3333]}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.