当前位置 : 首页 » 互动问答 » 正文

Java中的不可变数组

分类 : 互动问答 | 发布时间 : 2010-09-13 21:43:12 | 评论 : 14 | 浏览 : 77981 | 喜欢 : 125

Java中的原始数组是否有一个不可变的替代方法?创建一个原始数组final实际上并不会阻止一个人做类似

 final int [] array = new int [] {0,1,2,3};
array [0] = 42;

我希望数组的元素不可更改。

回答(14)

  • 1楼
  • 不是原始数组。您需要使用List或其他一些数据结构:

     List <Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
  • 2楼
  • 我的建议是不使用为此目的而存在的数组或 unmodifiableList but to use Guava's ImmutableList

     ImmutableList <Integer> values = ImmutableList.of(0,1,2,3);
  • 3楼
  • 正如其他人所说,你不能在Java中拥有不可变数组。

    如果你绝对需要一个方法来返回一个不影响原始数组的数组,那么你每次都需要克隆数组: notranslate> public int [] getFooArray(){   return fooArray == null? null:fooArray.clone(); }

    显然这是相当昂贵的(因为每次调用getter时都会创建一个完整的副本),但如果你不能改变界面(例如使用

    )并且不能冒险客户改变你的内部,然后它可能是必要的。List这种技术被称为防御性副本。

    This technique is called making a defensive copy.

  • 4楼
  • 有一种方法可以在Java中创建不可变数组:

     final String [] IMMUTABLE = new String [0];
    

    具有0个元素(显然)的数组不能变异。

    如果使用 final static String [] EMPTY_STRING_ARRAY = new String [0]; List <String> emptyList = new ArrayList <String>(); return emptyList.toArray(EMPTY_STRING_ARRAY); //返回EMPTY_STRING_ARRAY方法将List转换为数组,这实际上可以派上用场。因为即使空数组占用一些内存,也可以通过创建一个常量空数组来保存该内存分配,并始终将其传递给toArray方法。如果传递的数组没有足够的空间,该方法将分配一个新数组,但如果它有(列表为空),它将返回您传递的数组,允许您在调用<notranslate时重用该数组> on empty toArray List.toArray List.

    final static String[] EMPTY_STRING_ARRAY = new String[0];
    
    List<String> emptyList = new ArrayList<String>();
    return emptyList.toArray(EMPTY_STRING_ARRAY); // returns EMPTY_STRING_ARRAY
    
  • 5楼
  • 另一个答案

    静态类ImmutableArray <T> {
        private final T [] array;
    
        private ImmutableArray(T [] a){
            array = Arrays.copyOf(a,a.length);
        }
    
        public static <T> ImmutableArray <T> from(T [] a){
            返回新的ImmutableArray <T>(a);
        }
    
        public T get(int index){
            return array [index];
        }
    }
    
    {
        final ImmutableArray <String> sample = ImmutableArray.from(new String [] {“a”,“b”,“c”});
    }
  • 6楼
  • 如果您需要(出于性能原因或节省内存)原生'int'而不是'java.lang.Integer',那么您可能需要编写自己的包装类。网上有各种IntArray实现,但没有(我发现)是不可变的: Koders IntArray , Lucene IntArray。可能还有其他人。

  • 7楼
  • 从Guava 22开始,从包相比,内存占用更少,com.google.common.primitives 开始,你可以使用三个新类,与 ImmutableList .

    他们也有一个建设者。示例:

     int size = 2;
    ImmutableLongArray longArray = ImmutableLongArray.builder(size)
      。新增(1L)中
      。新增(2L)中
      。建立();
    

    或者,如果在编译时已知大小:

     ImmutableLongArray longArray = ImmutableLongArray.of(1L,2L);
    

    这是获取Java基元的数组的不可变视图的另一种方法。

  • 8楼
  • 从Java 9开始,您可以使用 List.of(...), JavaDoc.

    此方法返回一个不可变的List,效率非常高。

  • 9楼
  • 不,这是不可能的。但是,可以这样做:

     List <Integer> temp = new ArrayList <Integer>();
    temp.add(Integer.valueOf(0));
    temp.add(Integer.valueOf(2));
    temp.add(Integer.valueOf(3));
    temp.add(Integer.valueOf(4));
    List <Integer> immutable = Collections.unmodifiableList(temp);
    

    这需要使用包装器,它是一个List,而不是一个数组,但是它是你最接近的。

  • 10楼
  • 在某些情况下,使用Google Guava库中的静态方法会减轻重量: List <Integer> Ints.asList(int ... backingArray)

    Examples:

    • List <Integer> x1 = Ints.asList(0 ,1,2,3)
    • List <Integer> x1 = Ints.asList(new int [] {0,1,2,3}})
  • 11楼
  • 如果你想避免可变性和拳击,没有开箱即用的方法。但是您可以创建一个包含原始数组的类,并通过方法提供对元素的只读访问。

  • 12楼
  • 虽然 Collections.unmodifiableList()确实有效,但有时您可能会有一个大型库,其中已经定义了返回数组的方法(例如String[])。 为了防止破坏它们,您实际上可以定义将存储值的辅助数组:

     public class Test {
        private final String [] original;
        private final String []辅助;
        / **构造函数* /
        public Test(String [] _values){
            original = new String [_values.length];
            //预先分配的数组。
            auxiliary = new String [_values.length];
            System.arraycopy(_values,0,original,0,_values.length);
        }
        / **获取数组值。 * /
        public String [] getValues(){
            //无需调用clone() - 我们预先分配了辅助。
            System.arraycopy(original,0,auxiliary,0,original.length);
            返回辅助;
        }
    }
    

    To test:

    测试测试=新测试(new String [] {“a”,“b”,“C”});
        的System.out.println(Arrays.asList(test.getValues()));
        String [] values = test.getValues();
        值[0] =“foobar”;
        //此时,“foobar”存在于“辅助”中但是因为我们是
        //为每个电话复制“原始”到“辅助”,下一行
        //将打印原始值“a”,“b”,“c”。
        的System.out.println(Arrays.asList(test.getValues()));
    

    不完美,但至少你有“伪不可变数组”(从类的角度来看),这不会破坏相关的代码。

  • 13楼
  • The of(E ... elements) method in Java9可以用来创建不可变列表只需一行:

     List <Integer> items = List.of(1,2,3,4,5);
    

    上述方法返回包含任意数量元素的不可变列表。将任何整数添加到此列表将导致 java.lang.UnsupportedOperationException 异常。此方法还接受单个数组作为参数。

     String [] array = ...;
    List <String []> list = List。(String []> of(array);
  • 14楼
  • 嗯..数组作为常量传递(如果它们)作为变量参数是有用的。

相关阅读:

Converting a date string to a DateTime object using Joda Time library

Java reading a file into an ArrayList?

Remove duplicates from an array of objects in JavaScript

How to clear console in Java - Eclipse SDK

How many spaces will Java String.trim() remove?

How to print all key and values from HashMap in Android?

With android studio no jvm found, JAVA_HOME has been set

String isNullOrEmpty in Java?

The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

What does -XX:MaxPermSize do?