[英]How to create an object by accumulating two fields from a list of another object?
我有一个房间对象列表:
class Room {
int guestCount;
List<String> sunglassBrands;
}
我想让所有房间的客人总数和他们所有的太阳镜品牌像这样:
class Guest {
int guestCount;
List<Sunglass> sunglasses;
}
class Sunglass {
String brandName;
}
现在,这可能是一种直接的方法:
AtomicInteger numberOfGuests = new AtomicInteger();
List<Sunglass> sunglassBrandsList = new ArrayList<>();
rooms.forEach(
room -> {
numberOfGuests.getAndAdd(room.getGuestCount());
sunglassBrandsList.addAll(
room.getSunglassBrands.stream()
.map(
brand -> {
Sunglass sunglass = new Sunglass();
sunglass.setBrandName(brand);
return sunglass;
})
.collect(Collectors.toList()));
});
Guest guest = new Guest();
guest.setGuestCount(numberOfGuests.get());
guest.setSunglassBrands(sunglassBrandsList);
这可以在一次迭代中以更优雅的方式完成吗? 我想我可以在这里使用reduce
但我不太确定如何使用。
你可以用下一个方法来做。
int numberOfGuests = rooms.stream().mapToInt(Room::getGuestCount).sum();
List<Sunglass> sunglassBrands = rooms.stream().map(Room::getSunglassBrands).flatMap(List::stream).map(Sunglass::ofBrandName).collect(Collectors.toList());
// creation of object
注意: Sunglass::ofBrandName
是下一个实现的静态方法
public static Sunglass ofBrandName(String brandName) {
Sunglass sunglass = new Sunglass();
sunglass.brandName = brandName;
return sunglass;
}
你可以在你的类中创建一个私有方法来创建太阳镜或只是硬编码 lambda。
如果你想使用reduce
,你可以使用它的三参数版本。
Guest guest = rooms.stream()
.reduce(new Guest(),
(guest, room) -> {
guest.addGuests(room.getGuestCount());
guest.addSunglasses(room.getSunglassBrands()
.stream().map(Sunglass::new).collect(Collectors.toList()));
return guest;
},
(guest1, guest2) -> {
guest1.addGuests(guest2.getGuestCount());
guest1.addSunglasses(guest2.getSunglasses());
return guest1;
});
为此,我在Guest
类中添加了以下两个方法并初始化了实例变量。
class Guest {
int guestCount = 0;
List<Sunglass> sunglasses = new ArrayList<>();
public void addGuests(int guestCount) {
this.guestCount += guestCount;
}
public void addSunglasses(List<Sunglass> sunglasses) {
this.sunglasses.addAll(sunglasses);
}
}
并向Sunglass
类添加了一个构造函数。 (如果您不想这样做,必须将.map(Sunglass::new)
更改为 lambda 表达式以创建Sunglass
并设置品牌名称(就像您所做的那样)。
public Sunglass(String brandName) {
this.brandName = brandName;
}
您可以使用流将太阳镜列表转换为太阳镜对象,但除此之外,我会为房间使用常规循环。
Set<Sunglass>
而不是List<Sungclass>
以避免重复。List<Room> rooms = new ArrayList<>(
List.of(new Room(23, List.of("brandA, BrandB")),
new Room(33, List.of("brandC", "brandD"))));
Guest guest = new Guest();
for (Room room : rooms) {
// update the guest count here
guest.setGuestCount(
guest.getGuestCount() + room.getGuestCount());
// create a new list of Sunglass instances here.
// and add to the guest instance
guest.getSunglasses().addAll(room.getBrands().stream()
.map(Sunglass::new).collect(Collectors.toList()));
}
System.out.printl(guest);
印刷
[56, [brandA, BrandB, brandC, brandD]]
支持类定义。
class Room {
int guestCount;
List<String> sunglassBrands;
public Room(int count, List<String> list) {
this.guestCount = count;
this.sunglassBrands = list;
}
public int getGuestCount() {
return guestCount;
}
public List<String> getBrands() {
return sunglassBrands;
}
}
class Guest {
int guestCount = 0;
List<Sunglass> sunglasses = new ArrayList<>();
public int getGuestCount() {
return guestCount;
}
public void setGuestCount(int count) {
this.guestCount = count;
}
public List<Sunglass> getSunglasses() {
return sunglasses;
}
@Override
public String toString() {
return String.format("[%d, %s]", guestCount, sunglasses);
}
}
class Sunglass {
String brandName;
public Sunglass(String name) {
this.brandName = name;
}
@Override
public String toString() {
return brandName;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.