![](/img/trans.png)
[英]Using Java Streams to group together a List of objects by an attribute and reduce them to a new list of object with the average of another attribute
[英]Merge the data relating to each unique Object in a List and transform them into a List of another Type using Streams
我有一个 Bean 列表( List 1 ),我想将其转换为另一个列表( List 2 )。
我已经成功地做到了这一点。 但我觉得它太复杂了:再次挑出id
的 +循环+流。
我的问题是:是否有可能使它更简单?
样本数据 - List1:
[Customer [id=1, name=jon, carType=fiat, color=black],
Customer [id=2, name=din, carType=ford, color=yellow],
Customer [id=1, name=jon, carType=benz, color=white],
Customer [id=1, name=jon, carType=volvo, color=red],
Customer [id=3, name=fin, carType=volvo, color=black],
Customer [id=3, name=fin, carType=fiat, color=green],
Customer [id=4, name=lara, carType=bmw, color=red],
Customer [id=5, name=tina, carType=toyota, color=white],
Customer [id=5, name=tina, carType=fiat, color=yelow],
Customer [id=6, name=bogi, carType=benz, color=black]]
样本数据 - List2:
ImprovedCustomer [id=1, name=jon, cars=[Car [carType=fiat, color=black], Car [carType=benz, color=white], Car [carType=volvo, color=red]]]
ImprovedCustomer [id=2, name=din, cars=[Car [carType=ford, color=yellow]]]
ImprovedCustomer [id=3, name=fin, cars=[Car [carType=volvo, color=black], Car [carType=fiat, color=green]]]
ImprovedCustomer [id=4, name=lara, cars=[Car [carType=bmw, color=red]]]
ImprovedCustomer [id=5, name=tina, cars=[Car [carType=toyota, color=white], Car [carType=fiat, color=yelow]]]
ImprovedCustomer [id=6, name=bogi, cars=[Car [carType=benz, color=black]]]
我的代码:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class App {
public static void main(String[] args) {
List<Customer> list = new ArrayList<>();
list.add(new Customer(1, "jon", "fiat", "black"));
list.add(new Customer(2, "din", "ford", "yellow"));
list.add(new Customer(1, "jon", "benz", "white"));
list.add(new Customer(1, "jon", "volvo", "red"));
list.add(new Customer(3, "fin", "volvo", "black"));
list.add(new Customer(3, "fin", "fiat", "green"));
list.add(new Customer(4, "lara", "bmw", "red"));
list.add(new Customer(5, "tina", "toyota", "white"));
list.add(new Customer(5, "tina", "fiat", "yelow"));
list.add(new Customer(6, "bogi", "benz", "black"));
List<Integer> ids = list.stream().map(Customer::getId).distinct().collect(Collectors.toList());
List<ImprovedCustomer> ImprovedCustomers = new ArrayList<>();
for (int id : ids) {
ImprovedCustomer improvedCustomer = new ImprovedCustomer(id);
List<Car> collect = list.stream().filter(a -> a.getId().equals(id)).map(a -> {
if (improvedCustomer.getName() == null) {
improvedCustomer.setName(a.getName());
}
return new Car(a.getCarType(), a.getColor());
}).collect(Collectors.toList());
improvedCustomer.setCars(collect);
ImprovedCustomers.add(improvedCustomer);
}
}
}
class Customer {
private Integer id;
private String name;
private String carType;
private String color;
public Customer(Integer id, String name, String carType, String color) {
super();
this.id = id;
this.name = name;
this.carType = carType;
this.color = color;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCarType() {
return carType;
}
public void setCarType(String carType) {
this.carType = carType;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
class Car {
private String carType;
private String color;
public Car(String carType, String color) {
super();
this.carType = carType;
this.color = color;
}
public String getCarType() {
return carType;
}
public void setCarType(String carType) {
this.carType = carType;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
class ImprovedCustomer {
private Integer id;
private String name;
private List<Car> cars;
public ImprovedCustomer() {
super();
}
public ImprovedCustomer(Integer id) {
super();
this.id = id;
}
public ImprovedCustomer(Integer id, String name, List<Car> cars) {
super();
this.id = id;
this.name = name;
this.cars = cars;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
}
您当前的解决方案对每个唯一id
的客户列表执行迭代。
正如@Johannes Kuhn在评论中指出的那样,您可以通过使用收集器groupingBy(classifier, downstream)
来消除冗余迭代。 使用这个收集器,我们可以在一次迭代中将每个具有唯一id
的客户映射到汽车列表。
然后根据groupingBy()
生成的地图的每个条目构造一个ImprovedCustomer
对象列表。
注意:为了使用这种方法,要么Customer
类应该基于id
和name
属性实现equals/hashCode
契约,要么我们需要使用一个辅助记录(或类)来包装一个Customer
对象。 为简单起见,我假设我们可以依赖Customer
类的equals/hashCode
实现。
因此,在下面的代码中作为分类器函数,我应用了Function.identity()
(即,一个键将是客户本身)和作为下游收集器的收集器mapping()
和toList()
的组合,它将每个客户转换为Car
对象,并将映射到同一客户的汽车收集到一个列表中。
public static void main(String[] args) {
List<Customer> customers = // initializing the list of customers
List<ImprovedCustomer> improvedCustomers = customers.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.mapping(cust -> new Car(cust.getCarType(), cust.getColor()),
Collectors.toList())
))
.entrySet().stream()
.map(entry -> new ImprovedCustomer(entry.getKey().getId(), entry.getKey().getName(), entry.getValue()))
.collect(Collectors.toList());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.