Java 8 使用Java8流修改列表中对象的属性值

Java 8 使用Java8流修改列表中对象的属性值,java-8,java-stream,Java 8,Java Stream,我在ArrayList中有一个水果对象列表,我想将水果名修改为复数名 请参考以下示例: @Data @AllArgsConstructor @ToString class Fruit { long id; String name; String country; } List<Fruit> fruits = Lists.newArrayList(); fruits.add(new Fruit(1L, "Apple", "India")); fruits.a

我在ArrayList中有一个
水果
对象列表,我想将
水果名
修改为复数名

请参考以下示例:

@Data
@AllArgsConstructor
@ToString
class Fruit {

    long id;
    String name;
    String country;
}

List<Fruit> fruits = Lists.newArrayList();
fruits.add(new Fruit(1L, "Apple", "India"));
fruits.add(new Fruit(2L, "Pineapple", "India"));
fruits.add(new Fruit(3L, "Kiwi", "New Zealand"));

Comparator<Option> byNameComparator = (e1, e2) -> e1.getName().compareToIgnoreCase(e2.getName());

fruits = fruits.stream().filter(fruit -> "India".equals(fruit.getCountry()))
            .sorted(byNameComparator).collect(Collectors.toList());

List<Fruit> fruitsWithPluralNames = Lists.newArrayList();
for (Fruit fruit : fruits) {
    fruit.setName(fruit.getName() + "s");
    fruitsWithPluralNames.add(fruit);
}

System.out.println(fruitsWithPluralNames);

// which prints [Fruit(id=1, name=Apples, country=India), Fruit(id=2, name=Pineapples, country=India), Fruit(id=3, name=Kiwis, country=New Zealand)]
@数据
@AllArgsConstructor
@托斯特林
等级水果{
长id;
字符串名;
弦国;
}
List fruits=Lists.newArrayList();
添加(新水果(1L,“苹果”、“印度”);
水果。添加(新水果(2L,“菠萝”,“印度”);
添加(新水果(3L,“猕猴桃”、“新西兰”);
比较器byNameComparator=(e1,e2)->e1.getName().compareToIgnoreCase(e2.getName());
水果=水果.stream().filter(水果->印度.equals(水果.getCountry())
.sorted(byNameComparator).collect(collector.toList());
List FROUTSWITHPLURALNAME=Lists.newArrayList();
用于(水果:水果){
fruit.setName(fruit.getName()+“s”);
水果有多个名称。添加(水果);
}
System.out.println(带有多个名称的水果);
//它打印[水果(id=1,name=Apples,country=India),水果(id=2,name=菠萝,country=India),水果(id=3,name=Kiwis,country=newzealand)]


使用Java8流是否有任何方法可以实现相同的行为?

您可以只使用
forEach
。完全没有流:

fruits.forEach(fruit -> fruit.setName(fruit.getName() + "s"));

您可以使用下面的streams map函数,在新的流中获得结果,以便进一步处理

Stream<Fruit> newFruits = fruits.stream().map(fruit -> {fruit.name+="s"; return fruit;});
        newFruits.forEach(fruit->{
            System.out.println(fruit.name);
        });
Stream newFruits=fruits.Stream().map(水果->{fruit.name+=“s”;return fruit;});
新水果。forEach(水果->{
System.out.println(水果名称);
});

如果要创建新列表,请使用
Stream.map
方法:

List<Fruit> newList = fruits.stream()
    .map(f -> new Fruit(f.getId(), f.getName() + "s", f.getCountry()))
    .collect(Collectors.toList())

您可以使用
peek
来完成此操作

List<Fruit> newList = fruits.stream()
    .peek(f -> f.setName(f.getName() + "s"))
    .collect(Collectors.toList());
List newList=fruits.stream()
.peek(f->f.setName(f.getName()+“s”))
.collect(Collectors.toList());

仅为了修改对象集合中的某些属性,您可以直接将forEach与集合一起使用,如下所示

collection.forEach(c -> c.setXyz(c.getXyz + "a"))

将元素添加到新列表有什么意义?该列表与原始列表相同。对于剩下的任务,您不需要流:
fruits.forEach(fruit->fruit.setName(fruit.getName()+“s”)。顺便说一句,
列出了.newArrayList()
新ArrayList()相比没有优势
@SergeyLagutin和@Apostolos谢谢你的回复
Collection.forEach
loop非常好用。因为我刚刚更新了我的问题(添加了使用流对列表进行过滤和排序)。我们是否将复数名称功能与筛选和排序相结合?或者我们需要再次单独的
集合。forEach
?@BhaveshDangi排序操作将在复数列表中完成。你可以把它们结合起来,是的。请不要忘记接受答案。在这种情况下,使用Streams和forEach之间有什么性能差异吗?答案中似乎有一个小错误。endPeek方法中的“.map(f->new Fruit(f.getId(),f.getName()+“s”,f.getCountry())“line have one more closing”)”不应仅用于调试。API注意:此方法的存在主要是为了支持调试,您希望在元素流过管道中的某个点时看到它们:参考:我不明白为什么此操作“主要”用于调试。我不明白为什么JavaAPI会有“主要”用于调试的代码。操作就在那里,可以用于开发人员认为合适的任何用途。当然,开发人员必须了解它是如何工作的,并正确地使用它。对于这个问题,forEach是一个更好的答案,但是当你想继续这个流时,peek更合适(forEach在这种情况下甚至不起作用)。@Jordan Silva:我会使用map()而不是滥用peek():map(f->{f.setName(f.getName()+“s”);返回f;})@在我看来,在这种情况下使用
map
在语义上是错误的。除此之外,您还需要额外的代码使其工作。当添加到列表(如果“c”是列表)时,这不起作用。我得到java.util.ConcurrentModificationException这是正确的方法。forEach可以对当前列表执行此操作,而在Streams中,您必须执行返回新列表的操作
collection.forEach(c -> c.setXyz(c.getXyz + "a"))