收集副本

时间:2015-11-24 08:56:52

标签: java collections

你通常如何使用Java收集getter?例如,我有两个班级。

public class A
{
    String s = "1";
    A () {}
}

public class B
{
     List<A> list;
     public B()
     {
       list = new ArrayList<>();
     }
     public List<A> getList()
     {
        return list;
     }

}

如果我喜欢这样的话,我可以这样做:

B elem = new B();
elem.getList().add(new A());

所以它打破了吸气剂的想法。

我能做到

 public List<A> getList()
 {
     return new ArrayList<>(list);
 }

但是,如果我修改了一些结果元素,原始元素将会改变。

4 个答案:

答案 0 :(得分:5)

使用Collection.unmodifiableList(list)返回不可修改的集合:

public List<A> getList() {
    return Collections.unmodifiableList(list);
}

引用Javadoc:

  

返回指定列表的不可修改视图。此方法允许模块为用户提供对内部列表的“只读”访问。对返回列表的查询操作“通读”到指定列表,并尝试修改返回的列表,无论是直接还是通过其迭代器,都会产生UnsupportedOperationException

因此无法在返回的列表中追加/删除元素,也无法修改其元素。

如果您想要返回列表的深层克隆而不是不可修改的列表,请参阅this question

答案 1 :(得分:2)

如果您需要深层复印,可以

public List<A> getList() {
    return list.stream().map(A::copy).collect(toList());
}

更好的解决方案是首先不返回列表。您可以返回类似的内容。

public int getCount() { return list.size(); }

public String getASAt(int index) { return list.get(index).s; }

现在无法修改基础A对象,也无需冗余复制它们。

答案 2 :(得分:2)

通常我会在班上提供有意义的维护方法来管理列表。列表仅用于查看目的:

public class Foo
{
    private List<Bar> bars = ....;
    // or even stricter, returning Iterator<Bar>
    /** be clear in javadoc the list is immutable */
    public List<Bar> getBars() {
       return Collections.unmodifiableList(bars);
    }

    public void addBar(Bar bar) {
        this.bars.add(bar);
        // and maybe some other works against bar
    }
    public void removeBar(Bar bar) {
        this.bars.remove(bar);
        // and maybe some other works against bar
    }
    // even something more meaningful
    public void removeExpiredBars() {
        // iterate thru this.bar and remove all bars with bar.isExpired()
    }
}

始终提醒自己: getter的想法 (和setter)很糟糕。你不应该设计你的课程,以便从中获取数据&#34;。你应该为你的班级提供有意义的行为。

答案 3 :(得分:1)

您可以通过这种方式返回副本:

    public List<A> getList()
    {
       List<A> destination = new ArrayList<A> ( list.size());
       Collections.copy(destination , list);
       return destination ;
    }

<强> EDITED

这是最短的版本:

    public List<A> getList()
    {
       return new ArrayList<A> ( list);
    }