微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java 使用流中的重复元素创建多个列表

如何解决Java 使用流中的重复元素创建多个列表

我正在尝试获取一个列表并返回一个包含原始列表某些方面的 Map<String,List<String>,其中原始元素可以使用流作为不同键下的值多次出现。例如:

class Employee {
  String firstName;
  String lastName;
  Status status;
}

enum Status {
  FULL_TIME,PART_TIME
}

List<Employee> employees = List.of(
  new Employee("f1","l1",Status.PART_TIME),new Employee("f2","l2",Status.FULL_TIME),new Employee("f3","l3",new Employee("f4","l4",Status.FULL_TIME));

生成的映射应具有如下键,并且列表必须是不可变的:

fName: ["f1","f2","f3","f4"],lName: ["l1","l4"],fullTime: ["f2 l2","f4 l4"]

对于多个流来说这很容易,但是原始数据非常大,所以我试图一次性完成。如果有另一种我不知道的方法,我也可以使用 Guava 和 Apache Commons。谢谢!

编辑 1:展示我现在的做法

以下是我在三个流中所做的事情,我想将其简化为一个

var firstName = employees.stream()
        .map(e -> e.getFirstName())
        .collect(Collectors.toUnmodifiableList());
var lastName = employees.stream()
        .map(e -> e.getLastName())
        .collect(Collectors.toUnmodifiableList());
var fullTime = employees.stream()
        .filter(e -> e.getStatus().equals(Status.FULL_TIME))
        .collect(Collectors.toUnmodifiableList());

解决方法

这是一个示例,但您将添加一些额外的行和第三类。

主要

var employees = List.of(
        new Employee("f1","l1",Status.PART_TIME),new Employee("f2","l2",Status.FULL_TIME),new Employee("f3","l3",new Employee("f4","l4",Status.FULL_TIME)
);

var maps = employees.stream()
        .flatMap(employee -> Stream.of(
                new Pair("fName",employee.firstName),new Pair("lName",employee.lastName),new Pair(
                        employee.status == Status.FULL_TIME ? "fullTime" : "partTime",employee.firstName.concat(" ").concat(employee.lastName)
                )
        ))
        .filter(pair -> !pair.name.equals("partTime"))
        .collect(Collectors.groupingBy(
                pair -> pair.name,Collectors.mapping(pair -> pair.value,Collectors.toUnmodifiableList())
        ));

相关类

class Employee {
    String firstName;
    String lastName;
    Status status;

    //constructors,setters and getters
}

enum Status {
    FULL_TIME,PART_TIME
}

class Pair {
    String name;
    String value;

    //constructors,setters and getters
}
,

我建议您将每个生成列表的流放入方法中。像这样:

public static List<String> getListFirstName(List<Employee> employees) {
    return   employees.stream()
            .map(e -> e.getFirstName())
            .collect(Collectors.toUnmodifiableList());
}

public static List<String> getListLasttName(List<Employee> employees) {
    return  employees.stream()
            .map(e -> e.getLastName())
            .collect(Collectors.toUnmodifiableList());
}

public static List<String> getListFullTime(List<Employee> employees) {
    return  employees.stream()
            .filter(e -> e.getStatus().equals(Status.FULL_TIME))
            .map(e -> e.getFirstName()+" "+e.getLastName())
            .collect(Collectors.toUnmodifiableList());
}

public static List<String> getListPartTime(List<Employee> employees) {
    return  employees.stream()
            .filter(e ->e.getStatus().equals(Status.PART_TIME))
            .map(e -> e.getFirstName()+" "+e.getLastName())
            .collect(Collectors.toUnmodifiableList());
}

创建一个返回 Map 的方法,它采用员工列表和字符串条件来生成 Map(键是条件,值是包含所需数据的列表):

public static Map<String,List<String>> getByCriteria(String criteria,List<Employee> employees) {
    Map<String,List<String>>map =  new HashMap<>();
    
    if("fName".equals(criteria)) {
        map.put(criteria,getListFirstName(employees));
    }else if("lName".equals(criteria)) {
        map.put(criteria,getListFirstName(employees));
    }else if("fullTime".equals(criteria)) {
        map.put(criteria,getListFullTime(employees));
    }else if("partTime".equals(criteria)) {
        map.put(criteria,getListPartTime(employees));
    }
    return Collections.unmodifiableMap(map);
}

创建一个标准列表,例如:

    List<String> criterias = List.of("fName","lName","fullTime","partTime");

从标准列表创建流以生成包含您想要的内容的最终地图

Map<String,List<String>> collect = criterias.stream().parallel().map(c -> getByCriteria(c,employees)).flatMap(map -> map.entrySet().stream())
        .collect(Collectors.toMap(eM -> eM.getKey(),eM -> eM.getValue())); 

这里是完整的课程:

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        List<Employee> employees = List.of(new Employee("f1",Status.FULL_TIME));
        List<String> criterias = List.of("fName","partTime");
        
        Map<String,eM -> eM.getValue()));
        
        System.out.println(collect);
        

    }
    
    public static Map<String,List<Employee> employees) {
        Map<String,List<String>>map =  new HashMap<>();
        
        if("fName".equals(criteria)) {
            map.put(criteria,getListFirstName(employees));
        }else if("lName".equals(criteria)) {
            map.put(criteria,getListFirstName(employees));
        }else if("fullTime".equals(criteria)) {
            map.put(criteria,getListFullTime(employees));
        }else if("partTime".equals(criteria)) {
            map.put(criteria,getListPartTime(employees));
        }
        return Collections.unmodifiableMap(map);
    }
    
    public static List<String> getListFirstName(List<Employee> employees) {
        return   employees.stream()
                .map(e -> e.getFirstName())
                .collect(Collectors.toUnmodifiableList());
    }
    
    public static List<String> getListLasttName(List<Employee> employees) {
        return  employees.stream()
                .map(e -> e.getLastName())
                .collect(Collectors.toUnmodifiableList());
    }
    
    public static List<String> getListFullTime(List<Employee> employees) {
        return  employees.stream()
                .filter(e -> e.getStatus().equals(Status.FULL_TIME))
                .map(e -> e.getFirstName()+" "+e.getLastName())
                .collect(Collectors.toUnmodifiableList());
    }
    
    public static List<String> getListPartTime(List<Employee> employees) {
        return  employees.stream()
                .filter(e ->e.getStatus().equals(Status.PART_TIME))
                .map(e -> e.getFirstName()+" "+e.getLastName())
                .collect(Collectors.toUnmodifiableList());
    }

}
,

您可以将员工对象转换为 pairs 列表,其中对键是映射键,对值是列表的单个值。然后您可以通过键对这些对进行“分组”。

Map<String,List<String>> vals = employees.stream()
  .map(e -> Arrays.asList(
    Pair.of("fname",e.firstName),Pair.of("lname",e.lastName),e.status == Status.FULL_TIME ? Pair.of("fullTime",e.firstName + " " + e.lastName) : null
  ))
  .flatMap(Collection::stream)
  .filter(Objects::nonNull)
  .collect(Collectors.groupingBy(p -> p.getLeft(),Collectors.mapping(p -> p.getRight(),Collectors.toUnmodifiableList())));

但是这个解决方案的内存消耗比我的previous answer中的要差,特别是在处理大流时。

,

既然你说你可以使用apache commons,也许是这样的?

    Map<String,List<String>> map = new HashMap<>();
    List<Employee> employees = List.of(
            new Employee("f1",Status.FULL_TIME));

    List<String> firstNames = new ArrayList<>();
    List<String> lastNames = new ArrayList<>();
    List<String> ftEmployees = new ArrayList<>();

    employees.forEach(employee -> {
        firstNames.add(employee.firstName);
        lastNames.add(employee.lastName);
        if (employee.status == Status.FULL_TIME) {
            ftEmployees.add(employee.firstName + " " + employee.lastName);
        }
    });

    map.put("fname",ImmutableList.copyOf(firstNames));
    map.put("lName",ImmutableList.copyOf(lastNames));
    map.put("fullTime",ImmutableList.copyOf(ftEmployees));
,

这是可以执行您想要的操作的示例代码。不需要多个流,一个流就足以遍历对象。

        Map<String,List<String>> result = new HashMap<>();
        result.put("fname",new ArrayList<String>());
        result.put("lname",new ArrayList<String>());
        result.put("fullTime",new ArrayList<String>());
        List<Employee> employees = List.of(
                  new Employee("f1",Status.FULL_TIME));
        employees.forEach(e -> {
            result.get("fname").add(e.firstName);
            result.get("lname").add(e.lastName);
            result.get("fullTime").add(e.firstName + " " + e.lastName);
        });
        System.out.println(result);

我会让你把列表转换成不可变列表。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。