Java 有效使用集合。不可修改*()

Java 有效使用集合。不可修改*(),java,collections,Java,Collections,在考虑效率、代码可读性和其他标准时,公开集合的只读视图更可取的方法是什么?从效率的角度来看,使用methodA而不是methodB会有什么实际的区别吗?请考虑“代码>列表/代码>可能经常访问的情况,如GUI表的数据模型。 我假设collections.umodifiebleList()总是创建一个新对象,对吗 class A{ List<Object> list = new ArrayList<Object>(); List<Object> l

在考虑效率、代码可读性和其他标准时,公开集合的只读视图更可取的方法是什么?从效率的角度来看,使用
methodA
而不是
methodB
会有什么实际的区别吗?请考虑“代码>列表/代码>可能经常访问的情况,如GUI表的数据模型。

我假设
collections.umodifiebleList()
总是创建一个新对象,对吗

class A{
    List<Object> list = new ArrayList<Object>();
    List<Object> listReadOnly = Collections.unmodifiableList(list);

    List<Object> methodA(){
        return listReadOnly;
    }

    List<Object> methodB(){
        return Collections.unmodifiableList(list);
    }
}
A类{
列表=新的ArrayList();
List listReadOnly=集合。不可修改列表(List);
列表方法a(){
返回列表只读;
}
列表方法b(){
返回集合。不可修改列表(列表);
}
}

是的,
集合。不可修改列表每次都会创建一个新对象,但这是一个非常便宜的操作。(它没有太多工作要做。)

我不确定GUI的数据模型是否会一次又一次地获取集合—它显然会获取集合,然后对其进行迭代,但这是另一回事

如果它只是在每次有东西提示GUI数据发生更改时获取一个集合,那么这种情况将相对很少发生,我预计,而不是在“每秒数十万次”的范围内,这将是一个真正的瓶颈。我希望无论是什么代码调用它,都可能比创建不可修改列表所涉及的工作要多得多

基本上,这感觉像是一个微观优化太远了,除非你有证据表明它导致了一个问题。一如既往,您应该:

  • 定义性能要求
  • 以满足其他要求的最简单方式编写代码
  • 编写测试以检查您是否满足性能要求
  • 如果您目前没有满足这些要求,请仔细找出瓶颈所在(无论是使用探查器还是其他技术)
  • 以尽可能小的可读性损失修复这些瓶颈
  • 起泡、冲洗、重复

不要使用
方法a
,因为您必须在列表之间维护状态,这在多线程环境中可能很棘手,即使在单线程环境中也是一件痛苦的事情

执行
methodB
,让JDK整理效率(它非常快)

注意:除非列表中的元素本身是不可变的,否则methodB不是完全安全的,因为虽然列表可能是不可修改的,但其元素本身可能会被修改。考虑:

List<Date> list = new ArrayList<Date>();
list.add(new Date());
List<Date> dates = Collections.unmodifiableList(list);
Date date = dates.get(0);
date.setTime(0);  // The date in the original list has now changed!
List List=new ArrayList();
添加(新日期());
列表日期=集合。不可修改列表(列表);
日期=日期。获取(0);
日期。设置时间(0);//原始列表中的日期现在已更改!

虽然它违背了“使用接口,而不是类”,但当我使用番石榴
不可变*
类时,我使用实际类作为字段/返回类型。这让用户非常清楚,集合不能被修改。B只创建一个新对象(包装原始列表),但不执行深度复制。