我有一个雇员列表。
我重写了Employee类的equals和hashcode。 我想将员工列表转换为以员工对象作为键,并将唯一车号列表作为值进行映射。
P.S:列表中也可能有重复的键。因此,我应该合并列表中存在的汽车编号的值并放入地图中。
请找到下面我尝试使用迭代的代码。我想知道如何使用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;
}
}
答案 0 :(得分:1)
我喜欢获得一条命令性代码并将其转换为功能性代码... 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名称而不是对象作为键,因为它看起来很合适,无法选择一个雇员实例而不是另一个雇员实例,所以我使用了 key < / em>。
答案 1 :(得分:1)
只需使用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]}