Java 使用流中的重复元素创建多个列表
Java create multiple lists with duplicate elements from stream
我正在尝试获取一个列表 return 一个 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", Status.PART_TIME),
new Employee("f4", "l4", Status.FULL_TIME));
生成的映射应具有如下所示的键,并且列表必须是不可变的:
fName: ["f1", "f2", "f3", "f4"],
lName: ["l1", "l2", "l3", "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());
这是执行您想要的操作的示例代码。不需要多个流,仅一个流就足以遍历对象。
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", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME),
new Employee("f3", "l3", Status.PART_TIME),
new Employee("f4", "l4", 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);
我会留给你将列表转换为不可变列表。
我建议你把生成列表的每个流都放在方法中。像这样:
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());
}
创建一个方法,该方法 return 一个 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()));
这里是完整的 class:
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", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME), new Employee("f3", "l3", Status.PART_TIME),
new Employee("f4", "l4", Status.FULL_TIME));
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()));
System.out.println(collect);
}
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);
}
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())));
然而,此解决方案的内存消耗比我 中的解决方案差,特别是在处理大流时。
既然你说你可以使用 apache commons,也许是这样的?
Map<String, List<String>> map = new HashMap<>();
List<Employee> employees = List.of(
new Employee("f1", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME),
new Employee("f3", "l3", Status.PART_TIME),
new Employee("f4", "l4", 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));
这是一个示例,但您将添加一些额外的行和第三行 class。
主要
var employees = List.of(
new Employee("f1", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME),
new Employee("f3", "l3", Status.PART_TIME),
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())
));
相关classes
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
}
我正在尝试获取一个列表 return 一个 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", Status.PART_TIME),
new Employee("f4", "l4", Status.FULL_TIME));
生成的映射应具有如下所示的键,并且列表必须是不可变的:
fName: ["f1", "f2", "f3", "f4"],
lName: ["l1", "l2", "l3", "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());
这是执行您想要的操作的示例代码。不需要多个流,仅一个流就足以遍历对象。
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", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME),
new Employee("f3", "l3", Status.PART_TIME),
new Employee("f4", "l4", 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);
我会留给你将列表转换为不可变列表。
我建议你把生成列表的每个流都放在方法中。像这样:
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());
}
创建一个方法,该方法 return 一个 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()));
这里是完整的 class:
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", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME), new Employee("f3", "l3", Status.PART_TIME),
new Employee("f4", "l4", Status.FULL_TIME));
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()));
System.out.println(collect);
}
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);
}
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())));
然而,此解决方案的内存消耗比我
既然你说你可以使用 apache commons,也许是这样的?
Map<String, List<String>> map = new HashMap<>();
List<Employee> employees = List.of(
new Employee("f1", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME),
new Employee("f3", "l3", Status.PART_TIME),
new Employee("f4", "l4", 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));
这是一个示例,但您将添加一些额外的行和第三行 class。
主要
var employees = List.of(
new Employee("f1", "l1", Status.PART_TIME),
new Employee("f2", "l2", Status.FULL_TIME),
new Employee("f3", "l3", Status.PART_TIME),
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())
));
相关classes
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
}