如何使用java8将List <Employee>转换为Map <Employee,List <String >>?

时间:2019-08-23 10:35:20

标签: java java-8

我有一个雇员列表。

我重写了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;
    }

}

2 个答案:

答案 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]}