为什么没有 ArrayList(T[] t) 构造函数?

发布于 2024-10-04 22:04:11 字数 329 浏览 4 评论 0原文

以这种方式通过对象数组初始化列表是很常见的:

Foo[] objs = ...;
ArrayList<Foo> list = new ArrayList<Foo>(Arrays.asList(objs));

我想知道,ArrayList 的设计者是否有任何原因不包含以数组作为参数的构造函数,以便它可以这样初始化:

ArrayList<Foo> list = new ArrayList<Foo>(objs);

可能它违反了一些规定原则,线程安全还是其他什么?

It is very common to initialize list by array of objects in such way:

Foo[] objs = ...;
ArrayList<Foo> list = new ArrayList<Foo>(Arrays.asList(objs));

I wonder, is there any reason why desiners of ArrayList didn't include constructor with array as parameter, so that it could be initialized like that:

ArrayList<Foo> list = new ArrayList<Foo>(objs);

May be it violates some principles, thread-safety or something else?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅忆流年 2024-10-11 22:04:11

我不知道为什么它不在标准库中,但是 GuavaLists 类具有 < code>newArrayList 甚至有助于类型推断:(

ArrayList<Foo> list = Lists.newArrayList(objs);

如果您经常使用它,您可能需要静态导入 Lists.newArrayList 。)

I don't know why it's not in the standard library, but Guava's Lists class has newArrayList which even helps with type inference:

ArrayList<Foo> list = Lists.newArrayList(objs);

(You may want to import Lists.newArrayList statically if you use it a lot.)

错々过的事 2024-10-11 22:04:11

为此,您可以使用 Google Guava Library(又名 Google Collections):

String[] ary = {"a", "b"};
List<String> l = Lists.newArrayList(ary);

http://code.google。 com/p/guava-libraries/

You can use Google Guava Library (AKA Google Collections) for this:

String[] ary = {"a", "b"};
List<String> l = Lists.newArrayList(ary);

http://code.google.com/p/guava-libraries/

稚气少女 2024-10-11 22:04:11

看来ArrayList本身没有实现任何构造函数,而只是将调用委托给超类构造函数,即AbstractList的构造函数。有很多列表实现(包括 LinkedList)不应该具有接受数组的构造函数。

我认为类 Arrays 中缺少接受数组的构造函数和静态实用方法的存在是良好设计和更好的代码重用的一个例子。没错,它会导致我们编写更冗长的代码,但这就是代价。

顺便说一句,如果您使用静态 import java.util.Arrays 您可以调用 asList() 而无需提及数组,因此代码并不冗长。

It seems that the reason that ArrayList does not implement any constructor itself but just delegates the call to super class constructor, i.e. constructor of AbstractList. There are a lot of list implementations including LinkedList that should not have constructor that accepts array.

I think that absence of constructor that accepts array and presence of static utility method in class Arrays is an example of good design and better code reuse. That's right that it cause us to write a little bit more verbose code, but this is the price.

BTW if you are using static import java.util.Arrays you can then call asList() without mentioning Arrays, so the code is not to verbose.

ゃ懵逼小萝莉 2024-10-11 22:04:11

java.util.Arrays 内部使用其自己版本的 ArrayList 类...

private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable
{
 ...
}

不知道为什么它不包含为标准构造函数调用...但您可以按照领导 java.util.Arrays 并拥有您自己的 Arraylist 版本。

java.util.Arrays internally uses its own version of ArrayList class...

private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable
{
 ...
}

No idea why it is not included as a standard constructor call... but you can follow the lead of java.util.Arrays and have your own version of Arraylist.

若言繁花未落 2024-10-11 22:04:11

构造 new ArrayList(Arrays.asList(array)) 对我来说意义不大,我完全不记得它了。
早就应该这么做了,但迟到总比不做好。

 import java.lang.reflect.Field;
 import java.util.ArrayList;

 public class RealArrayList<E> extends ArrayList<E>{
    
    static final String ELEMENT_DATA_FIELD_NAME = "elementData";
    static final String SIZE_FIELD_NAME = "size";

    public <E> RealArrayList (E[] array){     
       try {
            Field elementDataField = getClass().getSuperclass()
                    .getDeclaredField(ELEMENT_DATA_FIELD_NAME);
            elementDataField.setAccessible(true); 
            elementDataField.set(this, array);
            Field sizeField = getClass().getSuperclass()
                    .getDeclaredField(SIZE_FIELD_NAME);
            sizeField.setAccessible(true);
            sizeField.set(this, array.length);
         } catch (Exception ex) {
            ex.printStackTrace();
         }
     }   
}

适用于包括字符串在内的对象。不适用于基元。为了使其与基元一起工作,可能应该为每个基元类型添加构造函数,并将项目转换为对象包装器。

更新。
这是适用于对象和基元的最终版本。
没有经过如此严格的测试。

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RealArrayList<E> extends ArrayList<E> {

static final String ELEMENT_DATA_FIELD_NAME = "elementData";
static final String SIZE_FIELD_NAME = "size";

public <E> RealArrayList(E[] array) {
    setElementDataAndSize(array);
}

public RealArrayList(int[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(byte[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(char[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(short[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(long[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(float[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(double[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(boolean[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

private <E> void setElementDataAndSize(E[] array) {
    getElementDataFieldAndSetValue(array);
    getSizeFieldAndSetValue(array.length);
}

private <E> void getElementDataFieldAndSetValue(E[] array) {
    try {
        Field field = getClass().getSuperclass().getDeclaredField(ELEMENT_DATA_FIELD_NAME);
        field.setAccessible(true);
        field.set(this, array);
    } catch (Exception ex) {
        Logger.getLogger(RealArrayList.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private void getSizeFieldAndSetValue(int size) {
    try {
        Field field = getClass().getSuperclass().getDeclaredField(SIZE_FIELD_NAME);
        field.setAccessible(true);
        field.set(this, size);
    } catch (Exception ex) {
        Logger.getLogger(RealArrayList.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private Object[] convertArrayOfPrimitivesToArrayOfObjects(Object array) {
    int arraylength = Array.getLength(array);
    Object[] outputArray = new Object[arraylength];
    for (int i = 0; i < arraylength; ++i) {
        outputArray[i] = Array.get(array, i);
    }
    return outputArray;
}

}

到目前为止,我发现的唯一问题是 realArrayList.remove('a') 抛出 IndexOutOfBoundsException。不知何故,ArrayList.remove('a') 将“a”视为整数而不是字符。解决方法是使用 remove(new Character('a'))

Construction new ArrayList<Foo>(Arrays.asList(array)) makes so little sense to me, that I am completely unable to remember it.
Should have done it long ago, but better late than never.

 import java.lang.reflect.Field;
 import java.util.ArrayList;

 public class RealArrayList<E> extends ArrayList<E>{
    
    static final String ELEMENT_DATA_FIELD_NAME = "elementData";
    static final String SIZE_FIELD_NAME = "size";

    public <E> RealArrayList (E[] array){     
       try {
            Field elementDataField = getClass().getSuperclass()
                    .getDeclaredField(ELEMENT_DATA_FIELD_NAME);
            elementDataField.setAccessible(true); 
            elementDataField.set(this, array);
            Field sizeField = getClass().getSuperclass()
                    .getDeclaredField(SIZE_FIELD_NAME);
            sizeField.setAccessible(true);
            sizeField.set(this, array.length);
         } catch (Exception ex) {
            ex.printStackTrace();
         }
     }   
}

Works with Objects including Strings. Does not work with primitives. To make it work with primitives, probably, should be added constructors for each primitive type with the conversion of items to object wrappers.

Update.
Here is the final version that works with objects and primitives.
Not so heavily tested.

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RealArrayList<E> extends ArrayList<E> {

static final String ELEMENT_DATA_FIELD_NAME = "elementData";
static final String SIZE_FIELD_NAME = "size";

public <E> RealArrayList(E[] array) {
    setElementDataAndSize(array);
}

public RealArrayList(int[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(byte[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(char[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(short[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(long[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(float[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(double[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

public RealArrayList(boolean[] array) {
    Object[] arrayOfObjects = convertArrayOfPrimitivesToArrayOfObjects(array);
    setElementDataAndSize(arrayOfObjects);
}

private <E> void setElementDataAndSize(E[] array) {
    getElementDataFieldAndSetValue(array);
    getSizeFieldAndSetValue(array.length);
}

private <E> void getElementDataFieldAndSetValue(E[] array) {
    try {
        Field field = getClass().getSuperclass().getDeclaredField(ELEMENT_DATA_FIELD_NAME);
        field.setAccessible(true);
        field.set(this, array);
    } catch (Exception ex) {
        Logger.getLogger(RealArrayList.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private void getSizeFieldAndSetValue(int size) {
    try {
        Field field = getClass().getSuperclass().getDeclaredField(SIZE_FIELD_NAME);
        field.setAccessible(true);
        field.set(this, size);
    } catch (Exception ex) {
        Logger.getLogger(RealArrayList.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private Object[] convertArrayOfPrimitivesToArrayOfObjects(Object array) {
    int arraylength = Array.getLength(array);
    Object[] outputArray = new Object[arraylength];
    for (int i = 0; i < arraylength; ++i) {
        outputArray[i] = Array.get(array, i);
    }
    return outputArray;
}

}

The only problem I found so far is that realArrayList.remove('a') throws IndexOutOfBoundsException. Somehow ArrayList.remove('a') treats 'a' as integer rather than character. Workaround is to use remove(new Character('a')).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文