当前位置: 首页 > 知识库问答 >
问题:

Java的流过滤器是创建新列表还是指向原始列表?

宗安翔
2023-03-14

我阅读了这个问题的答案:Java 8在使用流“过滤器”和“收集”后会创建一个新的列表吗?

但这不太符合我的经验...我想。我只是想确保我清楚情况。

考虑以下代码(可以在https://www . tutorialspoint . com/compile _ Java _ online . PHP上运行):

import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

public class ArrayPlay {

    public static class Person {
        private String first;
        private String last;
        private int id;
        private State state;
        private boolean thing;

        public Person(String first, String last, int id, boolean isThing) {
            this.id = id;
            this.first = first;
            this.last = last;
            this.thing = isThing;
        }

        public void setFirst(String first) { this.first = first; }
        public String getFirst() { return first; }

        public void setLast(String last) { this.last = last; }
        public String getLast() { return last; }

        public void setId(int id) { this.id = id; }
        public int getId() { return id; }

        public void setIsThing(boolean thing) { this.thing = thing; }
        public boolean isThing() { return thing; }
        
        public void setState(State state) { this.state = state; }
        public State getState() { return this.state; }

        @Override
        public String toString() {
            return String.valueOf(id) + ": " + first + " " + last + 
                (thing ? " and has thing" : "") + 
                (state != null ? " and is from " + state.getStateName() : "");
        }
    }

    public static class State {
        private String stateName;
        private String stateCode;
        private String country;

        public State() { }

        public String getStateName() { return stateName; }
        public void setStateName(String name) { this.stateName = name; }

        public String getStateCode() { return stateCode; }
        public void setStateCode(String code) { this.stateCode = code; }

        public String getCountry() { return country; }
        public void setCountry(String country) { this.country = country; }

        public static State newStateCode(String code) {
            State state = new State();
            state.setStateCode(code);
            return state;
        }
        
        public static final class Builder {
            private State state;
            
            private Builder() { state = new State(); }
            
            public static Builder aState() { return new Builder(); }
            
            public Builder withName(String name) { state.setStateName(name); return this;}
            public Builder withCode(String code) { state.setStateCode(code); return this;}
            public Builder withCountry(String country) { state.setCountry(country); return this;}
            
            public State build() { return state; }
        }
    }

    public static void main(String[] args) {
        List<Person> people = new ArrayList<Person>() {{
            add(new Person("ffej", "llensog", 13482839, true));
            add(new Person("knarf", "knarfson", 39940000, false));
            add(new Person("Mary", "Contrary", 82233888, true));
        }};

        System.out.println("\nSet State for filtered Persons");
        List<Person> hasThing = people.stream().filter(p -> p.isThing()).collect(Collectors.toList());
        System.out.println("Before setting state.");
        people.forEach(p -> System.out.println("people: " + p));
        hasThing.forEach(p -> p.setState(State.Builder.aState().withName("Alabama").build()));
        System.out.println("After setting state.");
        people.forEach(p -> System.out.println("people: " + p));
    
        hasThing.forEach(p -> System.out.println("hasThing: " + p));
    }
}

我期望的结果如下:

et State for filtered Persons
Before setting state.
people: 13482839: Daphne llensog and has thing
people: 39940000: Daphne knarfson
people: 82233888: Daphne Contrary and has thing
After setting state.
people: 13482839: Daphne llensog and has thing
people: 39940000: Daphne knarfson
people: 82233888: Daphne Contrary and has thing
hasThing: 13482839: Daphne llensog and has thing and is from Alabama
hasThing: 82233888: Daphne Contrary and has thing and is from Alabama

但我得到的实际结果是:

et State for filtered Persons
Before setting state.
people: 13482839: Daphne llensog and has thing
people: 39940000: Daphne knarfson
people: 82233888: Daphne Contrary and has thing
After setting state.
people: 13482839: Daphne llensog and has thing and is from Alabama
people: 39940000: Daphne knarfson
people: 82233888: Daphne Contrary and has thing and is from Alabama
hasThing: 13482839: Daphne llensog and has thing and is from Alabama
hasThing: 82233888: Daphne Contrary and has thing and is from Alabama

由于某种原因,当我在< code > hasting 的< code>forEach上运行< code>setState时,它也在修改< code>people中的对象。如果< code>filter(...).collect()创建一个新列表。对于这个我不理解的行为,有什么好的解释吗?

共有1个答案

何烨华
2023-03-14

听着这很简单。该列表将作为ArrayList实例。而不是列表中包含的对象。因为您修改了列表包含的实例,所以它在两个列表中都显示为已修改

它还在修改人身上的物体。这对我来说没有意义,如果过滤器(...)。收集()

当然,它会修改这些对象。列表只是保存对象实例引用的集合。

在您的情况下,您有2个集合(列表)保存对相同实例的引用。使用1个列表来修改对象的状态将反映到两个列表。

这是一个简单的图形表示

使用 ref2 修改实例的状态,它实际上修改 ref4 指向的同一实例

 类似资料:
  • 我正在寻找在Java-8中过滤列表的最干净的方法,用一个简单的lambda ,而不用创建一个新的列表。 特别是,这种解决方案不合适,因为返回一个新的: 注意,下面的解决方案也不起作用,因为列表应该< code>clear()其原始值(但是很明显,如果您在过滤之前清除它,就没有什么可过滤的了...): (此外,我更喜欢不使用第三方库或框架的解决方案)

  • 问题内容: 有没有办法在Java中创建原始int或任何原始类型的列表,如下所示? 看来我能做到 并将“ int”添加到此列表中。但这意味着我可以在此列表中添加任何内容。 我唯一的选择是创建一个int数组并将其转换为一个列表或创建一个Integer对象的列表吗? 问题答案: 在Java中,任何变量的类型都是原始类型或引用类型。泛型类型参数必须是引用类型。由于基元不扩展,因此它们不能用作参数化类型的泛

  • 我有一个物体,如下所示 给定MyObject的列表,是否可以使用Java8个流来过滤类型和子类型? 目前为止我有 但在这一部分中,我还希望在每个子类型上使用另一个过滤器来过滤特定子类型上的过滤器。我想不出怎么做。 例如 我会传入匹配类型B和子类型Z,所以我希望得到一个结果- 以下当前返回列表中的2个项目。 但是我想在每个子类型上添加一个额外的过滤器,并且只匹配“Z”存在的地方。

  • 上述代码的输出是: 但是我很困惑为什么list1没有被修改,因为list1和list2都首先引用同一个列表对象。有人能帮我理解这里到底发生了什么吗?

  • 过滤字段的列表,每一个成员应该是数组或对象 $data = [ ['id'=>1, 'name'=>'a'], ['id'=>2, 'name'=>'b'], ]; // 两个毫无意义的实例化写法 $list = new FilterableList; $list = new FilterableList($data); // 只保留 name 字段 $list = new Fi

  • 问题内容: 我在此论坛和Google中搜索后发布了查询,但无法解决相同的问题。 我正在尝试根据列表1中的值过滤列表2(多列)。 码 在上面的代码中,如果我提供特定值,则可以过滤,但不确定如何检查列表2中的Car Name是否在列表1中退出。 希望我面对的问题很清楚,等待指导(对于Java来说还是比较新的,因此,如果上述查询非常基础,请原谅)。 编辑, 我相信上面提供的链接3应该可以解决,但就我而言