简体   繁体   English

如何转换列表<Employee>到地图<Employee, List<String> &gt; 使用 java8?

[英]How do I convert a List<Employee> to Map<Employee, List<String>> using java8?

I have a list of Employee.我有一份员工名单。

I have overridden equals and hashcode of Employee class.我已经覆盖了 Employee 类的 equals 和 hashcode。 I want to convert employee list to map with employee object as key and list of unique car numbers as values.我想将员工列表转换为以员工对象为键并以唯一车号列表为值的映射

PS: there may be duplicate keys as well in the list. PS:列表中也可能有重复的键。 Hence I should merge the values of car numbers present in the list and put into the map.因此,我应该合并列表中存在的汽车编号的值并放入地图中。

Please find the code below which I tried using iteration.请在下面找到我尝试使用迭代的代码。 I wanted to know how this can be done using java 8.我想知道如何使用 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;
    }

}

I like to get a piece of imperative code and translate it into functional ... still java streams produce ugly code like the following...我喜欢获取一段命令式代码并将其转换为函数式......仍然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);

It will print :它将打印:

  {Employee [empName=A]=[car1, car2, car3, car4], Employee [empName=B]=[car111, car222, car333], Employee [empName=C]=[car1111, car2222, car3333]}

I would not do it, too ugly , too contrieved...我不会这样做,太丑了,太做作......

Especially if you compare it with native functional language like scala...特别是如果你将它与像 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))

In java I would consider using vavr to do so wich would result in this code:在 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);

In both Vavr code and scala I used the Employee name instead of the object as a key, beacuse it seems just proper, there is no way to choose one employee instance instead of another, so I used the key .在 Vavr 代码和 scala 中,我使用 Employee 名称而不是对象作为键,因为它看起来很合适,无法选择一个员工实例而不是另一个,所以我使用了

Could be solved simply by using Set instead of List :可以简单地通过使用Set而不是List来解决:

Map<Employee, Set<String>> collect = employeeList.stream()
            .collect(Collectors.groupingBy(Function.identity(),
                    Collectors.flatMapping(employee -> employee.getCars().stream(), Collectors.toSet())));

Output:输出:

{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.

相关问题 转换 Map <string,list<person> &gt; 至 Map <string,list<employee> &gt;,使用 Java 8 个流。 我这样做了,但是没有 for 循环怎么做</string,list<employee></string,list<person> - Convert Map<String,List<Person>> to Map<String,List<Employee>>, using Java 8 streams. I did this but how do this without for loop Java 8过滤器映射 <String,List<Employee> &gt; - Java 8 Filter Map<String,List<Employee>> 如何转换清单 <Object> 进入清单 <Map<String,String> &gt;在Java8中 - How to convert List<Object> into List<Map<String,String>> in java8 Java8将Map列表转换为字符串列表 - Java8 convert List of Map to List of string 如何根据薪水对员工 object 进行排序,姓名从 Map 升序排列<string, map<string, arraylist<employee> &gt;&gt;使用 Java8 流 API</string,> - How to sort Employee object based on salary,name in ascending order from Map<String, Map<String, ArrayList<Employee>>>using Java8 streams API 转换清单的方法 <Employee> 从`到地图 <Integer,List<Employee> &gt;` - Method to convert `List<Employee>` to `Map<Integer,List<Employee>>` 转换列表<String>列出<Employee>或列表<MyCustomClass> - Convert List<String> to List<Employee> or List<MyCustomClass> Java 8,列表 <Employee> 映射部门和地址列表 - java 8,List<Employee> to map of department and list of addresses 排序列表<employee>里面 Map <string, list<employee> > 基于键</string,></employee> - SortList<Employee> inside Map<String, List<Employee>> based on key 如何转换列表<map<string, string> > 进入包含 java8 中 map 值的列表</map<string,> - how to convert List<Map<String, String>> into the list containing the values of the map in java8
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM