Array是固定长度的,元素类型可以是基本类型,创建后大小不可改变;ArrayList是可变长 度的,只能存储对象,可以动态添加和删除元素。
区别1:
存储类型不同
Array:只可存储基本数据类型和对象
ArrayList:只能存储对象
区别2:
大小不同
Array:被设置为固定大小
ArrayList:是一个可变数组,大小可自动调整
区别3:
对象所包含的方法不同
Array:所包含的方法没有ArrayList多
ArrayList有很多操作方法:addAll、removeAll、iteration等
ArrayList可以存储基础类型。但是需要注意的是,当我们把基本数据类型存入ArrayList时,Java会自动为它创建一个包装类。例如,如果我们有一个ArrayList存储int类型的数据,Java实际上会把它当作Integer对象来处理。
ArrayList list = new ArrayList<>();
list.add(1); // 自动装箱,实际上是list.add(Integer.valueOf(1));
int num = list.get(0); // 自动拆箱,实际上是int num = list.get(0).intValue();
poll()方法从队列头部获取并删除元素,如果队列为空则返回null;remove()方法从队列头 部获取并删除元素,如果队列为空会抛出NoSuchElementException异常。
在 Java 的 Queue
接口中,poll()
和 remove()
方法都可以用于移除并返回队列的头部元素。然而,它们在处理队列为空的情况时表现出不同的行为:
remove()
: 当队列为空时,此方法会抛出一个 NoSuchElementException
。也就是说,如果你尝试从一个空的队列中移除元素,remove()
会失败并报错。poll()
: 当队列为空时,此方法会返回 null
而不是抛出异常。也就是说,如果你尝试从一个空的队列中移除元素,poll()
会静默地失败并返回 null
。Vector、Hashtable、Collections类的synchronizedXxx方法生成的集合,以及 ConcurrentHashMap等集合类是线程安全的。
在Java中,以下是一些线程安全的集合类:
Vector
:这是一个旧的集合类,线程安全,但是其性能低于ArrayList
。Vector
的所有方法都被synchronized
修饰,因此在多线程环境下是安全的。Hashtable
:类似于HashMap
,但是线程安全。所有公共的Hashtable
方法都使用synchronized
,所以多个线程可以共享单个Hashtable
。然而,与Vector
一样,Hashtable
也没有达到最高的性能。Collections.synchronizedList()
, Collections.synchronizedMap()
, Collections.synchronizedSet()
: Java Collections 框架提供了工具来转换其他集合为线程安全集合。通过在这些集合的所有公共方法上使用synchronized
关键字。CopyOnWriteArrayList
, CopyOnWriteArraySet
: 这些是专为多线程环境设计的集合类。它们采用了一种"写时复制"(copy-on-write)策略,当修改这些集合时,它们会创建底层数组的新副本,然后在新副本上进行修改。这使得这些集合在读取时不需要同步,从而提供了很高的读取性能。ConcurrentHashMap
: 这是一个线程安全的HashMap
实现,设计用于高并发场景。它使用了一种叫做分段锁的技术,允许多个修改操作并行进行。BlockingQueue
接口及其实现类(如 ArrayBlockingQueue
, LinkedBlockingQueue
, PriorityBlockingQueue
, SynchronousQueue
, DelayQueue
, PriorityQueue
等):这些队列是线程安全的,可以在多线程环境中安全地使用。以上就是Java中一些线程安全的集合类。在多线程环境下使用这些类可以避免并发问题。
迭代器是一种用于遍历集合元素的接口,提供了统一的遍历方式,使得遍历过程更加简洁和 灵活。
迭代器(Iterator)是一种接口,它为各种不同的数据结构提供了统一的访问机制。迭代器允许程序以顺序方式访问容器(如列表、队列、集合、映射等)中的元素,而不必关心底层实现细节。
迭代器的基本用法是,首先使用 hasNext() 方法检查容器中是否有下一个元素,如果有,则使用 next() 方法获取下一个元素。这种迭代方式可以遍历整个容器,直到所有元素都被访问过。
迭代器在Java、C++等编程语言中都有广泛的应用,它使得程序可以以一致的方式处理不同的数据结构,提高了代码的可读性和可维护性。
通过调用集合的iterator()方法获取迭代器对象,然后使用hasNext()判断是否有下一个元 素,使用next()获取下一个元素。迭代器的特点是只能单向遍历,不支持修改操作
迭代器(Iterator)是一种设计模式,它使对象能够遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常用于列表、数组和其他类型的集合数据。
以下是使用迭代器的一些基本方法:
iterator()
方法来获取迭代器。例如,在Java中,可以使用 List
接口的 iterator()
方法来获取迭代器。hasNext()
方法,可以判断集合中是否有下一个元素。next()
方法,可以获取下一个元素。以下是使用迭代器遍历列表的Java代码示例:
List |
|
list.add("apple"); |
|
list.add("banana"); |
|
list.add("orange"); |
|
Iterator |
|
while (iterator.hasNext()) { |
|
String fruit = iterator.next(); |
|
System.out.println(fruit); |
|
} |
输出结果:
apple |
|
banana |
|
orange |
迭代器的主要特点包括:
Iterator用于遍历集合,只能单向遍历,不支持修改操作;ListIterator是Iterator的扩展, 支持双向遍历,还可以在遍历过程中修改集合。
Iterator
和 ListIterator
都是用于遍历集合的接口,但是它们之间存在一些重要的区别:
Iterator
是集合的迭代器接口,它定义了遍历集合的方法,如 hasNext()
和 next()
。而 ListIterator
是 List
的迭代器接口,它继承自 Iterator
接口并添加了一些专门用于列表的迭代方法,如 hasPrevious()
、previous()
和 add()
。Iterator
只能从前往后遍历集合,无法从后往前遍历。而 ListIterator
可以从前往后或从后往前遍历列表。Iterator
只能用于遍历,没有其他功能。而 ListIterator
除了可以遍历列表外,还可以在列表中插入元素(通过 add()
方法)和获取当前元素(通过 next()
或 previous()
方法)。总的来说,ListIterator
是 Iterator
的一个特殊版本,专门用于遍历和操作列表。如果你需要遍历列表并可能需要在列表中插入元素,你应该使用 ListIterator
。如果你只需要遍历集合,可以使用 Iterator
。
7.怎么确保一个集合不能被修改?
可以使用Collections.unmodifiableXxx方法,将集合转换为不可修改的视图,尝试修改会 抛出UnsupportedOperationException异常。
在Java中,你可以通过使用 Collections.unmodifiableCollection()
或者 Collections.unmodifiableList()
方法来创建一个不可修改的集合。这样,你就能够确保集合的内容不会被改变。
例如:
List |
|
list.add("Hello"); |
|
list.add("World"); |
|
List |
|
// 下面的代码会抛出 UnsupportedOperationException |
|
// unmodifiableList.add("China"); |
如果你想要创建一个不可修改的集合,并且该集合是 Set
类型,你可以使用 Collections.unmodifiableSet()
方法。对于 Map
类型,你可以使用 Collections.unmodifiableMap()
方法。
这些方法都返回一个视图,表示由原始集合中的元素组成的不可修改的集合。原始集合不会被冻结,仍然可以修改。修改原始集合将立即反映在视图中,视图将抛出 UnsupportedOperationException
表示它不可修改。