【问题标题】:How to create an object by accumulating two fields from a list of another object?如何通过从另一个对象的列表中累积两个字段来创建一个对象?
【发布时间】:2021-06-22 16:26:48
【问题描述】:

我有一个房间的对象列表:

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,但我不太确定如何使用。

【问题讨论】:

    标签: java collections java-stream


    【解决方案1】:

    你可以用下一个方法。

    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。

    【讨论】:

      【解决方案2】:

      如果你想使用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;
      }
      

      【讨论】:

        【解决方案3】:

        您可以使用流将太阳镜列表转换为 Sunglass 对象,但除此之外,我会为房间使用常规循环。

        • 只需分配一个来宾实例。
        • 并使用 getter 和 setter 更新实例。
        • 根据您的要求,您可能希望使用Set&lt;Sunglass&gt; 而不是List&lt;Sungclass&gt; 以避免重复。
        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;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-10-29
          • 1970-01-01
          • 1970-01-01
          • 2018-10-10
          • 1970-01-01
          • 1970-01-01
          • 2019-10-26
          • 1970-01-01
          • 2021-05-27
          相关资源
          最近更新 更多