GVKun编程网logo

谷歌的ImmutableList和Collections.unmodifiableList()有什么区别?(google list)

18

在这篇文章中,我们将为您详细介绍谷歌的ImmutableList和Collections.unmodifiableList的内容,并且讨论关于有什么区别?的相关问题。此外,我们还会涉及一些关于Coll

在这篇文章中,我们将为您详细介绍谷歌的ImmutableList和Collections.unmodifiableList的内容,并且讨论关于有什么区别?的相关问题。此外,我们还会涉及一些关于Collections.emptyList()和Collections.EMPTY_LIST有什么区别、Collections.unmodifiableCollection、Collections.unmodifiableList 方法的使用与场景、Collections.unmodifiableList和防御性副本的知识,以帮助您更全面地了解这个主题。

本文目录一览:

谷歌的ImmutableList和Collections.unmodifiableList()有什么区别?(google list)

谷歌的ImmutableList和Collections.unmodifiableList()有什么区别?(google list)

从ImmutableList javadocs:

与Collections.unmodifiableList(java.util.List)(它是仍可以更改的单独集合的视图)不同,ImmutableList实例包含其自己的私有数据,并且永远不会更改。ImmutableList对于公共静态最终列表(“常量列表”)非常方便,并且还使您可以轻松地创建由调用者提供给您的类的列表的“防御性副本”。

这是否意味着:

  1. 如果我有Dimension对象的ImmutableList(例如),那么我无法更改其中的任何Dimension对象?
  2. 如果我有Dimension对象的Collections.unmodifiableList(列表),那么我不仅只能添加或删除任何对象,而且可以更改它们(例如,调用setDimension(width,height)方法)?

答案1

小编典典

不,不变性仅适用于中的对象的数量和引用Collection,而不能解决您放入中的对象的可变性Collection

不可变列表优于标准JDK的地方Collections.unmodifiableList在于,通过使用ImmutableList该列表,可以确保所引用的对象,它们的顺序和列表的大小不会从任何源更改。随着Collections.unmodifiableList如果别的东西有基础列表的引用,该代码可以修改列表,即使你有一个不可修改的列表的引用。

但是,如果要实现真正的不变性,则必须用不变的对象填充列表。

Collections.emptyList()和Collections.EMPTY_LIST有什么区别

Collections.emptyList()和Collections.EMPTY_LIST有什么区别

在Java中,我们具有Collections.emptyList()和Collections.EMPTY_LIST。两者具有相同的属性:

返回空列表(不可变)。该列表是可序列化的。

那么使用一个或另一个之间的确切区别是什么?

Collections.unmodifiableCollection

Collections.unmodifiableCollection

Collections.unmodifiableCollection这个可以得到一个集合的镜像,它的返回结果不可直接被改变,否则会提示

java.lang.UnsupportedOperationException  
    at java.util.Collections$UnmodifiableCollection.add(Collections.java:1018)

为了就是保护数据不要被改变。另外,修改原Collections时,会同时修改对应的镜像。

public class CollectionsTest {  
      
    @Test  
    public void test(){  
        Collection<String> c = new ArrayList<String>();  
          
        Collection<String> s = Collections.unmodifiableCollection(c);  
          
        c.add("str");  
          
        System.out.println(s);  
    }  
  
}

此时c集合被修改,s集合也会发生变化。

Collections.unmodifiableList 方法的使用与场景

Collections.unmodifiableList 方法的使用与场景

在《重构 —— 改善既有代码的设计》一书中,有一种重构手法叫 Encapsulate Collection
(封装集群),为了演示该重构手法,我写了四个类,通过对比重构前后的代码,加深对
这一重构手法的理解。

类 Student 有一 ArrayList 属性,如果没有阅读《重构 —— 改善既有代码的设计》一书,
很多人可能会像我一样,如下设计类 Student。但是,如果通过 Student.getCourses ()
获得对 ArrayList 属性引用后,就可以任意为 Student 对象添加 “课程”,而 Student 对象
对此一无所知,这不符合面向对象编程的习惯。

package com.readonlylist;

import java.util.ArrayList;

public class Student
{
    private String name;

    private ArrayList<String> courses;

    public Student(String name, ArrayList<String> courses)
    {
 this.name = name;
 this.courses = courses;
    }
    
    public ArrayList<String> getCourses()
    {
        return courses;
    }

    public void setCourses(ArrayList<String> courses)
    {
        this.courses = courses;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }    
}

package com.readonlylist;

import java.util.ArrayList;

public class Test
{
    public static void main(String[] args)
    {
 ArrayList<String> list = new ArrayList<String>();
 list.add("001");
 list.add("002");
        Student s = new Student("Tom", list);
        
        ArrayList<String> anotherList = s.getCourses();
        
        anotherList.add("999");
        
        System.out.println("Tom''s course.length = " + s.getCourses().size());
    }
}

重构后的 Student 类如下所示:

package com.readonlylist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Student1
{
    private String name;

    private ArrayList<String> courses;
    
    public Student1(String name, ArrayList<String> courses)
    {
 this.name = name;
 this.courses = courses;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
    
    public void addCourse(String course)
    {
 courses.add(course);
    }
    
    public String removeCourse(String course)
    {
 boolean removed = courses.remove(courses);
 
 if (removed)
 {
     return course;
 }
 else
 {
            return null;
 }
    }
    
    public List<String> getCourses()
    {
 return Collections.unmodifiableList(courses);
    }
}

package com.readonlylist;

import java.util.List;
import java.util.ArrayList;

public class Test1
{
    public static void main(String[] args)
    {
 ArrayList<String> list = new ArrayList<String>();
 list.add("001");
 list.add("002");
        Student1 s = new Student1("Tom", list);
        
        List<String> anotherList = s.getCourses();
        
        /**
         * throws java.lang.UnsupportedOperationException
         * should replace with s.addCourse(String course)
         */
        anotherList.add("999"); 
        
        // never reached
        System.out.println("Tom''s course.length = " + s.getCourses().size());        
    }
}

重构后,Student1 类,仅对外提供的 getCourses () 方法,而没有 setCourses () 方法,而且
通过 getCourses () 方法获得的 courses 是 “只读的”,如果你试图向其添加一个新课程,则
抛出 java.lang.UnsupportedOperationException。你必须通过 Student1.addCourse () 来
向特定的 Student1 对象添加一个新课程。就好像,你必须让顾客自己向购物车里放食物,
而不能在顾客毫不知情下,偷偷向其购物车里放食物。

Collections.unmodifiableList和防御性副本

Collections.unmodifiableList和防御性副本

如果我写

List<Integer> a1 = Arrays.asList(1,2,3);
List<Integer> a2 = Collections.unmodifiableList(a1);

a2 是只读的,但是如果我写

a1.set(0,10);

然后a2也被修改。

如果在API中表示:

返回指定集合的​​不可修改视图。此方法允许模块为用户提供对内部集合的“只读”访问权限。

那么,为什么如果我修改原始集合又修改了目标复制的集合?

也许我误解了含义,如果是的话,写一份防御性副本的方式是什么?

关于谷歌的ImmutableList和Collections.unmodifiableList有什么区别?的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Collections.emptyList()和Collections.EMPTY_LIST有什么区别、Collections.unmodifiableCollection、Collections.unmodifiableList 方法的使用与场景、Collections.unmodifiableList和防御性副本的相关信息,请在本站寻找。

本文标签: