[Java] 数组的备忘录

目标

由于对Java数组的处理方法分布在多个类中,因此需要整理一下。
这里不会对每个方法进行详细解释。

基本的事情 de

    • 配列はオブジェクト

 

    • 多次元配列は、配列の配列であらわす

 

    • 配列は共変(covariant)

 

    Iterableではないけど、拡張forループに使用可能

数组的浅拷贝

将现有数组的整体或部分复制

java.lang.System类的arraycopy()方法

创建一个新的相同数组实例

数组对象的克隆操作

    • キャスト不要

 

    CloneNotSupportedExceptionもキャッチ不要
private int[] values;

public void setValues(int[] values) {
    // 防御的コピー
    this.values = values.clone();
}

通过指定大小或生成新的子数组。

    • java.util.Arrays#copyOf()

 

    java.util.Arrays#copyOfRange()

将数组列表化

java.util.Arrays#asList()的汉语本地化表达只有一个选项 : “java.util.Arrays#asList()”。

    • リストのサイズが変わる操作は不可(add,remove,clearなど)

 

    • 要素の値が変わる操作はOK。

 

    • リストの要素を変えると、配列の要素も変わる

 

    要素がプリミティブ型の場合には、可変引数で渡すことはできるけど、配列として渡すことはできないので注意。

对原始类型数组进行列表化(提案)

我可以为必要的原始类型数组准备以下的实用方法,但是每次都会进行自动装箱操作。

public static List<Integer> asList(final int[] array) {
    return new AbstractList<Integer>() {
        @Override
        public Integer get(int index) {
            return array[index];
        }

        @Override
        public Integer set(int index, Integer element) {
            int oldValue = array[index];
            array[index] = element;
            return oldValue;
        }

        @Override
        public int size() {
            return array.length;
        }
    };
}

或许应该实现java.util.RandomAccess。

将列表转换为数组

    • java.util.List#toArray()

 

    java.util.List#toArray(T[])

请按照以下描述进行汉语的本土化改写,只需要一个选项:
例1:

List<String> list = getList();

// 引数無しは Object[] を返す
Object[] array = list.toArray();

例2:请帮我预定一张明天下午5点的火车票。

// 十分なサイズの配列を渡せば、その配列が返ってくる
String[] strings = list.toArray(new String[list.size()]);

请帮我把以下句子用中文进行本地化改写,只需要一个版本:

例3:

private static final String[] EMPTY_STRINGS = new String[0];

// ...

// サイズが足りない場合には、新しい配列を生成して返してくれる
String[] strings = list.toArray(EMPTY_STRINGS);

将数组和流进行相互转换。

    • java.util.Arrays#stream() – 配列のストリーム化

 

    java.util.stream.Stream#toArray() – ストリームの配列化

还有针对原始类型的支持,例如IntStream#toArray()等。

反思

似乎不能通过Class#getDeclaredFields()或Class#getDeclaredMethods()等方法获取数组对象的length字段或clone()方法。

不过,为了处理数组反射,可以使用 java.lang.reflect.Array 类。

判断对象是否为数组。

java.lang.Class的isArray()

获取数组元素的类型

java.lang.Class类的getComponentType()方法

获取数组的长度

java.lang.reflect.Array#getLength() 的含义是获取数组的长度。

获取、设置数组的元素

    • java.lang.reflect.Array#get()

 

    java.lang.reflect.Array#set()

使用get()和set()方法处理原始类型会自动进行装箱和拆箱。
还有一些用于处理原始类型的getInt()、getLong()、setInt()、setLong()等方法。

生成一个数组

创建一个新的数组实例。

将数组转化为字符串

如果想要显示数组的内容等情况,可以使用java.util.Arrays类的方法,其toString()方法与Object类的相同。

    • 1次元配列

 

    • java.util.Arrays#toString()

 

    • 多次元配列

 

    java.util.Arrays#deepToString()

如果传递给 deepToString() 的数组对象是一个具有自我循环引用的数组,则可能会发生严重问题(如堆栈溢出、无限循环等)。

排序

在Java中,可以通过`java.util.Arrays`类的方法来进行排序。

    • java.util.Arrays#sort()

 

    java.util.Arrays#parallelSort()

混合

使用java.util.Arrays#asList()和java.util.Colllections#shuffle()可以实现与排序类似的功能。

List<String> list = Arrays.asList(array);
Collections.shuffle(list);

如果是原始类型,可能只能自行努力了。

其他

其他实用方法基本上都在 java.util.Arrays 类中。

    • fill : 値埋め

 

    • equals : 一致チェック

 

    • deepEquals : ネスト配列の一致チェック

 

    • binarySearch : バイナリサーチ(ソート済みである必要あり)

 

    • hashCode : ハッシュ値計算

 

    deepHashCode : ネスト配列のハッシュ値計算

如果需要的话,可以使用上述的Arrays#equals()或Arrays#hashCode()方法,因为配列对象的equals()和hashCode()与Object类的实现相同。

而对于 deep~() 系列方法来说,需要确保不传递自己循环引用的参数。

数组类的名称

尝试获取数组类的各种名称后,可以得到以下感觉:

Integer[][] array = new Integer[0][0];
Class<?> clazz = array.getClass();
System.out.println("Name         : " + clazz.getName());
System.out.println("SimpleName   : " + clazz.getSimpleName());
System.out.println("CanonicalName: " + clazz.getCanonicalName());
System.out.println("TypeName     : " + clazz.getTypeName());
Name         : [[Ljava.lang.Integer;
SimpleName   : Integer[][]
CanonicalName: java.lang.Integer[][]
TypeName     : java.lang.Integer[][]

一个长度为0的数组。

通常,数组是可修改的对象,即使将其声明为final也可以进行修正。

然而,由于没有可更改的部分,零个数组是一个不可变的对象。因此,可以将其视为常量,也可以在多线程中共享使用而没有问题。

private static final Object[] EMPTY_OBJS = new Object[0];

位或布尔值数组

应该说 java.util.BitSet 的内存效率更好。

广告
将在 10 秒后关闭
bannerAds