繁体   English   中英

如何通过从另一个对象的列表中累积两个字段来创建对象?

[英]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;
}

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

  • 只需分配一个访客实例。
  • 并使用 getter 和 setter 更新实例。
  • 根据您的要求,您可能希望使用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;
    }
}

如何创建列表<object>带有字段字符串和 Map <string, set<string> &gt; 从另一个列表<object2><div id="text_translate"><p> Class Object2具有标准的 getter 并具有String字段folder 、 file和version 。 它被命名为SourceInfo</p><p> List&lt;SourceInfo&gt; source包含上面提到的三个字段。</p><p> 我的目标是从List&lt;SourceInfo&gt;创建一个List&lt;Info&gt; &gt; 。</p><p> 新List的 class 为Info ,如下图所示。</p><pre> public class Info { private final String folder; private final Map&lt;String, Set&lt;String&gt;&gt; file; public static Builder builder() { return new Builder(); } public static Builder builder(Info info) { return new Builder(info); } private Info(Builder builder) { this.folder = builder.folder; this.file = builder.file; } public String getFolder() { return folder; } public Map&lt;String, Set&lt;String&gt;&gt; getFile() { return file; } // autogenerated toString, hashCode, and equals public static class Builder { private String folder; private Map&lt;String, Set&lt;String&gt;&gt; file; private Builder() {} private Builder(Info info) { this.folder = info.folder; this.file = info.file; } public Builder with(Consumer&lt;Builder&gt; consumer) { consumer.accept(this); return this; } public Builder withFolder(String folder) { this.folder = folder; return this; } public Builder withFile(Map&lt;String, Set&lt;String&gt;&gt; file) { this.file = file; return this; } public Info build() { return new Info(this); } }</pre><p> 到目前为止,我尝试的是在构建器模式中创建一个集合。</p><pre> List&lt;SourceInfo&gt; source; // error: gc overhead limit exceeded List&lt;Info&gt; infoList = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet())))).build()).collect(Collectors.toList()); Map&lt;String, Set&lt;String&gt;&gt; map = source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet()))); List&lt;Info&gt; info = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))).build()).collect(Collectors.toList());</pre><p> 所需的 output。 以下语法可能已关闭。</p><pre> // [String, Map&lt;String, Set&lt;String&gt;&gt;] Info [folder, [key=file [value=version]]]...</pre><p> 我是 Java 的新手,不胜感激。</p><p> 我想了解如何使用 java8 和 for 循环来做到这一点。</p><p> 谢谢你。</p></div></object2></string,></object>

[英]How to create a List<Object> with fields String and Map<String, Set<String>> from another List<Object2>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何创建列表<object>带有字段字符串和 Map <string, set<string> &gt; 从另一个列表<object2><div id="text_translate"><p> Class Object2具有标准的 getter 并具有String字段folder 、 file和version 。 它被命名为SourceInfo</p><p> List&lt;SourceInfo&gt; source包含上面提到的三个字段。</p><p> 我的目标是从List&lt;SourceInfo&gt;创建一个List&lt;Info&gt; &gt; 。</p><p> 新List的 class 为Info ,如下图所示。</p><pre> public class Info { private final String folder; private final Map&lt;String, Set&lt;String&gt;&gt; file; public static Builder builder() { return new Builder(); } public static Builder builder(Info info) { return new Builder(info); } private Info(Builder builder) { this.folder = builder.folder; this.file = builder.file; } public String getFolder() { return folder; } public Map&lt;String, Set&lt;String&gt;&gt; getFile() { return file; } // autogenerated toString, hashCode, and equals public static class Builder { private String folder; private Map&lt;String, Set&lt;String&gt;&gt; file; private Builder() {} private Builder(Info info) { this.folder = info.folder; this.file = info.file; } public Builder with(Consumer&lt;Builder&gt; consumer) { consumer.accept(this); return this; } public Builder withFolder(String folder) { this.folder = folder; return this; } public Builder withFile(Map&lt;String, Set&lt;String&gt;&gt; file) { this.file = file; return this; } public Info build() { return new Info(this); } }</pre><p> 到目前为止,我尝试的是在构建器模式中创建一个集合。</p><pre> List&lt;SourceInfo&gt; source; // error: gc overhead limit exceeded List&lt;Info&gt; infoList = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet())))).build()).collect(Collectors.toList()); Map&lt;String, Set&lt;String&gt;&gt; map = source.stream().collect(Collectors.groupingBy(SourceInfo::getKey, Collectors.mapping(SourceInfo::getVersion, Collectors.toSet()))); List&lt;Info&gt; info = source.stream().map(e -&gt; Info.builder().withFolder(e.getFolder()).withFile(map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))).build()).collect(Collectors.toList());</pre><p> 所需的 output。 以下语法可能已关闭。</p><pre> // [String, Map&lt;String, Set&lt;String&gt;&gt;] Info [folder, [key=file [value=version]]]...</pre><p> 我是 Java 的新手,不胜感激。</p><p> 我想了解如何使用 java8 和 for 循环来做到这一点。</p><p> 谢谢你。</p></div></object2></string,></object> 如何使用两个对象字段对列表进行排序? 如何将对象的两个字段收集到同一个列表中? 如何在main方法中从另一个类创建List对象? 如何从对象创建/引用另一个对象? 如何从两种不同类型的列表创建对象列表 如何使用Modelmapper更新另一个对象的对象字段 Java 8 Streams:如何匹配两个 ArrayList 字符串之间的值并创建另一个 object 的列表 Java 8 - 如何在另一个列表中的 object 的列表中设置 object? 将匹配字段从一个 object 列表复制到 java 中的另一个 object 列表
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM