Java 中 Array 和 ArrayList 的比较和转换

在 Java 编程中,arrays 和 arraylists 都是基本的数据结构,用来存放数据集合。虽然两者的用途一样,但是它们的特点极大地影响应用的性能和灵活性。

本文探讨 arrays 和 arraylists 的重要特性,它们各自的强项和弱点。当需要的时候,实现两种数据结构的无缝转换。

1. 介绍

在 Java 中,ArrayList 是集合框架的一部分,是可调整数据结构的实现。这一位意味着 arraylist 内部维护了一个需要动态增长或者收缩的数组。

1.1 Java Arrays

array 是一个固定大小的数据结构,在连续的内存空间中存放相同类型的数据。 array 中的每个元素通过索引或者位置识别,首个元素从 0 开始。

Java 语言中的 arrays 跟其他语言中的数组类似。通常,它们有下面的特性:

  • Arrays 通常存储同种数据类型的元素。数据的类型在初始化的时候就已经定义好。
  • 一个整数类型数组只能存放整数。Java 的编译器不允许在整数类型的数组中存放字符串数据。
  • 数组中的每个元素只能通过索引获取。没有其他获取数组元素的方法。
  • 数组的大小通常是固定的并且不能更改。要存放比数组大小更多的元素,我们必须创建新的数组,然后将旧数组数据拷贝到新数组。当我们尝试添加超过数组大小的元素,将会抛出 ** ArrayIndexOutOfBoundsException** 错误。

比如,以下数组是其在内部存储器的表现:

java复制代码int [] a = new int[5];

a[0] = 1;
a[1] = 2;
a[2] = 4;
a[3] = 8;
a[4] = 16;

Array-in-memory.png

Arrays 有一个固定的长度,这就是说一旦数组被创建,数组大小不可以被改变。数组中元素的获取通过响应的索引获取。

java复制代码for(int i = 0; i < a.length; i++) {
  System.out.println(a[i]);
}

1.2 Java ArrayList

ArrayList 类是 Java 集合框架的一部分,用来实现 List 接口。不像 arrays,ArrayLists 伴随着元素的添加或者移除来增长或者缩小。

可以在 arraylist 中存放多种类型的元素,但是通常不推荐,因为在运行时获取数组元素时可能会引发 ClassCastException 异常。为了确保类型安全,泛型 generics 被用来声明存储在 arraylist 中的元素类型。

java复制代码List<Integer> arraylist = new ArrayList<>();

arraylist.add(1); // allowed

// arraylist.add("one"); // NOT allowed

除了可以使用 for 循环来顺序获取之外,arraylist 也允许使用迭代器来获取,比如 ListIterator。当我们使用迭代器并使用迭代器修改集合时,不会抛出 ConcurrentModificationException 异常。

java复制代码List<Integer> arraylist = new ArrayList<>();

arraylist.add(1);
arraylist.add(2);
arraylist.add(3);

// 1 - using foreach loop
arraylist.forEach(System.out::println)

// 2 - using iterator
ListIterator<Integer> listIterator = arraylist.listIterator();
while(listIterator.hasNext()) {
  System.out.println(listiterator.next());
}

2. Java 中 Array 和 ArrayList 的不同

下面的表格是 arrays 和 arraylists 的比较总结。比较这两个数据机构,基于它们的性能,使用和场景。

特性

Arrays

ArrayLists

固定大小和动态大小

在初始化的时候就分配固定大小

动态调整大小,随着元素的添加或删除而变化

内存管理和效率

如果数组大小超出了实际需要的个数,固定大小可能导致内存浪费

动态调整大小会带来轻微的性能开销,但是可以优化内存使用

语法和使用难易

初始化,增加,移除和更新操作语法很直白

使用 Collections API 方法更直观、更方便工作

性能

对于读/写操作,arrays 通常很快,因为它是直接使用元素索引获取。对于需要调整大小的写操作,arraylists 性能优于 array

除了需要调整大小的写操作,其他的操作 arraylists 表现得比 arrays 差

类型安全

Arrays 具有有限的类型安全性,并允许任何类型的元素存储在同个数组中

通过泛型,ArrayLists 提供更好的类型安全性,确保特定类型的元素被存储

最佳使用场景

当需要固定大小的集合并且看中内存效率,则使用 array

ArrayList 最适合用于小型的集合,其中方便性微小且可忽略的性能提升

3. Array 转换为 ArrayList

将 Array 转换为 ArrayList 最直接的方法是使用 Arrays.asList() 方法,该方法创建了数组的列表视图,然后我们使用 ArrayList 构造函数创建一个新的 ArrayList。这有效地将数组转换为 ArrayList。

java复制代码String[] array = {"apple", "banana", "cherry"};

ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(array));

另外,我们也可以使用 Java 8 streams 来迭代数组元素,并将它们收集在一个新的 ArrayList 中。它给我们提供了在将元素收集到列表前对数组的每个元素执行额外操作的机会。

java复制代码ArrayList<String> arrayList = Arrays.stream(array)
    // additional actions
    .collect(Collectors.toCollection(ArrayList::new));

4. ArrayList 转换为 Array

最简单的转换一个 arraylist 为 array 方案是使用 ArrayList.toArray() 方法,该方法返回一个包含列表中所有元素的数组,并且元素顺序正确。toArray() 返回 Object[] 类型的数组,所以你需要提供你想要的数组类型作为参数。

新数组的大小是由 ArrayList 大小决定的。

java复制代码ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("apple");
arrayList.add("banana");
arrayList.add("cherry");

String[] array = arrayList.toArray(new String[arrayList.size()]);

5. 最佳实践和推荐

ArrayLists 和 arrays 都有相同的目的和各自的优点。以下建议是有助于我们缩小范围并选择适合我们应用程序的正确数据结构。

5.1 频繁更改大小操作

因为特殊的需求,如果数组需要频繁更改大小,建议使用 ArrayList。 调整大小操作的内部处理消除了应用程序代码的复杂度,并提供了和手动修改相似的性能增益。

5.2 性能提升的可量化

如果性能提升不是很重要,那么还是推荐使用 arraylists。 ArrayLists 避免了复杂性,并且让代码可读性更高,且性能在处理小的集合跟 array 相似。

衡量性能增益的最佳方式是使用诸如 JMH 之类的工具进行测量。

5.3 原始类型 VS 包装对象

Array 可以直接处理原始类型,而 arraylists 则与对象(即包装类)一起使用。 如果在应用程序中处理它们时需要不断进行两种类型的转换,最好使用 arrays,因为它们会消除不必要的类型转换来简化代码,并因此带来轻微的性能提升。

java复制代码int[] array = new int[10];

//Creating arraylist for 'int' type is not possible. We must create arraylist of type 'Integer'

ArrayList<Integer> arraylist = new ArrayList<>();

5.4 与其他集合类型互操

ArrayList 是 Java 集合框架的一部分,所以和其他类型(比如:Map,Set)的操作是无缝的。使用 arrays 将会产生转换成其他类型不必要的额外步骤。

使用 arraylist 将减少这类的转换,因此代码可读性更高且更简洁。

6. 总结

总之,Java 开发的最佳实践通常推荐使用 ArrayLists 和其他内置的集合类,因为它们更灵活,并且相比中等大小的集合性能相似。

然而,arrays 也有实用的场景,特别是在意性能和内存效率的情况。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值