如何使用 Java stream() 加入两个具有共同 属性 的不同签名类型的列表?

how to join two List of different signature type with a common property using Java stream()?

class ScannedCoupon{
    Long id;
    String scannedcode;
}
        
class WinnerCoupon{
    Long id;
    String winnercode;
    boolean won;
}
    
List<ScannedCoupon> scannedCouponList;
List<WinnerCoupon> winnerCouponList;

这是我的案例:

我有两个列表 scannedCouponList 有 30 个项目,winnerCouponList 有 200 个。一个是用户扫描的代码,另一个是获胜者列表。如果 ScannedCoupon 的任何 scannedcodewinnerCouponList.

中,我想更新 winnerCouponList

如果 scannedCouponList 中的任何 winnercode == scannedcode 使用java stream() ?

我不想对 200 WinnerCoupon 一遍又一遍地使用循环,无论它们是否在 scannedCouponList 中。

我们在 winnerCouponList 上循环,同时对于每个 winnerCoupon 我们签入 scannedCoupon 列表有 scannedCode == winnerCode。 如果是,那么我们更新 winnerCoupon.won = true。如果没有,我们将继续循环,直到找到 scannedCode == winnerCode 或到达 scannedCouponList

的末尾
winnerCouponList.stream()
   .forEach(winnerCoupon -> {
       scannedCouponList.stream()
       .filter(scannedCoupon -> {
           return scannedCoupon.scannedcode.equals(winnerCoupon.winnercode);
       })
       .limit(1)
       .forEach(scannedCoupon -> winnerCoupon.won = true);
   });

首先您可以将扫码收集到一个Set.

Set<String> scannedCodes = scannedCouponList.stream()
                                            .map(ScannedCoupon::getScannedCode)
                                            .collect(Collectors.toSet());

由于 Set.contains 具有 O(1) 时间复杂度,因此上述设置有助于避免为每个获胜者优惠券循环扫描列表。 现在,流式传输获胜者优惠券列表并检查代码是否在 scannedCodes:

中可用
winnerCouponList.stream()
                .filter(coupon -> scannedCodes.contains(coupon.getWinnerCode()))
                .forEach(coupon -> coupon.setWon(true));

由于获胜者列表的大小远远超过您扫描的列表,这将具有大约 O(n) 的时间复杂度(考虑到扫描列表的大小与获胜者列表相比非常小),其中 n是获胜者名单的大小。

winnerCouponList.stream()
    .filter(w -> scannedCouponList.stream()
    .anyMatch(s -> s.scannedcode.equals(w.winnercode)))
    .forEach(w -> w.setWon(true));