Java SE 基础:List 集合列表
目录
List 接口概述
Arrays.asList、subList 注意事项
LinkedList 双向链表
ArrayList 数组列表
Vector 同步向量
Stack 栈
CopyOnWriteArrayList
集合遍历方式汇总
List 集合元素去重
List 接口概述
1、Collection 是最基本的集合接口,一个 Collection 代表一组对象(Object). 2、List 与 Set 继承 Collection 接口,而 Map 与 Collection 无关 |
1、List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置
2、用户能够使用索引(元素在List中的位置)来访问List中的元素,类似于Java的数组。
3、因为根据索引检索元素,所以List中允许存在相同的元素。
4、除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,修改元素,还能向前或向后遍历元素。
5、实现List接口的常用类有:LinkedList,ArrayList,Vector和Stack。
boolean retainAll(Collection<?> c):求与集合 c 的交集, |
T[] toArray(T[] a):list 转数组 1、{@link Arrays#asList(java.lang.Object[])} 返回的是 Arrays 的内部类 {@link Arrays.ArrayList},而并不是 java.util.ArrayList 2、内部类继承关系:private static class ArrayList<E> extends AbstractList<E> extends AbstractCollection<E> implements List<E> 3、Arrays 的内部类 {@link ArrayList} 只重写了部分方法,而 add、remove 方法是没有重写的,在 AbstractList 中直接抛的异常 throw new UnsupportedOperationException(); 4、asList 返回的集合如果调用 add、remove 等方法,就会抛出异常 UnsupportedOperationException - 不支持的操作 |
removeAll(Collection<?> c):从列表中移除所有包含在指定集合中的元素(可选操作) |
Arrays.asList、subList 注意事项
1、List 与 数组互相转换
public static void main(String[] args) {Object[] ids = new String[]{"100", "200", "300"};List<Object> dataList = Arrays.asList(ids);Object[] objects = dataList.toArray();//<T> T[] toArray(T[] a):返回指定类型的数组。参数 a 与返回值是同一个对象.String[] strings = dataList.toArray(new String[dataList.size()]);System.out.println(dataList);//[100, 200, 300]System.out.println(Arrays.asList(objects));//[100, 200, 300]System.out.println(Arrays.asList(strings));//[100, 200, 300]}
2、注意事项:
/*** 1、{@link Arrays#asList(java.lang.Object[])} 返回的是 Arrays 的内部类 {@link Arrays.ArrayList},而并不是 java.util.ArrayList* 2、内部类继承关系:private static class ArrayList<E> extends AbstractList<E> extends AbstractCollection<E> implements List<E>* 3、Arrays 的内部类 {@link Arrays.ArrayList} 只重写了部分方法,而 add、remove 方法是没有重写的,在 AbstractList 中直接抛的异常 throw new UnsupportedOperationException();*/@Testpublic void asList() {//一定要注意 Arrays.asList 返回的 ArrayList 并不是 java.util.ArrayList,而只是 Arrays 的一个内部类,它没有重写 add、remove 方法//调用就会抛出异常 UnsupportedOperationException - 不支持的操作List<Integer> integerList = Arrays.asList(12, 22, 32, 23);integerList.add(999);}
Arrays.asList 声明后不要再调用 add 等方法修改集合,否则会报 UnsupportedOperationException 异常。
3、ArrayList 的 subList 方法注意事项:
修改原集合元素的值,会影响子集合
修改子集合元素的值,会影响原集合
修改原集合的结构,当再访问子集合时,会引起 ConcurrentModificationException 异常.
修改子集合的结构,当再访问原集合时,会引起 ConcurrentModificationException 异常.
LinkedList 双向链表
1、LinkedList 双链表实现了 List 接口,允许 null 元素。
2、LinkedList 提供额外的 addFirst、addLast、getFirst、getLast、removeFirst、removeLast 等方法操作 LinkedList 的首部或尾部。
3、LinkedList 没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步。
public class LinkedList<E> extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable {...#内部类 Node,一个 Node 对象包含了列表当前索引的数据,又包含了当前索引的前后指向的节点private static class Node<E> {E item;//当期数据Node<E> next;//指向的前一个 Node(节点)Node<E> prev;//指向的后一个 Node(节点)Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}
...#向末尾添加元素public boolean add(E e) {linkLast(e);return true;}
...void linkLast(E e) {final Node<E> l = last;//获取末尾节点到局部变量 lfinal Node<E> newNode = new Node<>(l, e, null);//创建新的节点last = newNode;//将新节点赋给末尾节点if (l == null)//如果之前末尾节点为null,则说明整个列表为空first = newNode;//此时新加的节点也就是第一个元素elsel.next = newNode;//否则末尾节点不为null时,末尾节点的下一个节点为新加的节点size++;modCount++;}
...#向列表中间的指定位置添加元素public void add(int index, E element) {checkPositionIndex(index);//检查是否越界: index >= 0 && index <= size;if (index == size)linkLast(element);//如果添加的位置等于列表大小,则等同于添加在末尾else//node(index) 表示获取此索引处的节点linkBefore(element, node(index));//否则进行改变链表的前后指向}
...void linkBefore(E e, Node<E> succ) {// assert succ != null;final Node<E> pred = succ.prev;//获取当前节点的前一个节点//创建新节点,同时指定此节点的前节点、后节点final Node<E> newNode = new Node<>(pred, e, succ);succ.prev = newNode;//将 succ 节点切换到新节点后面if (pred == null)first = newNode;//如果之前本身前节点为 null,则elsepred.next = newNode;//交换位置size++;modCount++;}
ArrayList 数组列表
1、ArrayList 实现了可变大小的数组,允许存在相同元素,包括 null。大致相当于 Vector,不同之处在于它是不同步的。
2、ArrayList 没有实现同步,多个线程同时访问一个List,则必须自己实现访问同步
3、每个 ArrayList 实例都有一个容量 。 容量是用于存储列表中的元素的数组的大小。 它总是至少与列表大小一样大。 当元素添加到ArrayList时,其容量会自动增长。
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
//成员变量private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};transient Object[] elementData; // non-private to simplify nested class access...//构造器...public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}
...public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
...public boolean add(E e) {ensureCapacityInternal(size + 1); //调整数组列表的容量保存与当期大小一致elementData[size++] = e;return true;}
...public boolean remove(Object o) {if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {fastRemove(index);return true;}} else {for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;}
...
4、应用程序可以使用 ensureCapacity(int minCapacity) 增加此 ArrayList 实例的容量,以确保它至少可以容纳最小容量参数指定的元素数。
5、API 在线演示源码:src/main/java/org/example/collection/ArrayListTest.java · 汪少棠/java-se - Gitee.com
Vector 同步向量
1、Vector 类可以实现可增长的对象数组,与数组一样,它包含可以使用整数索引进行访问的组件,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。
2、Vector
是同步的,它在方法上设置了 synchronized 关键字,添加了 对象锁。
3、Vector 大致相当于 ArrayList,不同之处在 Vector 是线程安全的,而 ArrayList 是线程不安全的。
4、当需要扩容时,Vector 默认增长为原来一培,而 ArrayList 却是原来的一半。
public class java.util.Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
...#属性protected Object[] elementData;protected int elementCount;
...public Vector() {this(10);}public Vector(int initialCapacity) {this(initialCapacity, 0);}/*** @param initialCapacity 初始化容量* @param capacityIncrement 容量增量。即元素个数达到容量极限后的增加量*/public Vector(int initialCapacity, int capacityIncrement) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);this.elementData = new Object[initialCapacity];//数组方式存储this.capacityIncrement = capacityIncrement;}
...public synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;}public synchronized boolean removeElement(Object obj) {modCount++;int i = indexOf(obj);if (i >= 0) {removeElementAt(i);return true;}return false;}
...
在线演示源码:src/main/java/org/example/collection/VectorTest.java · 汪少棠/java-se - Gitee.com
Stack 栈
1、Stack 继承自 Vector,实现一个后进先出的堆栈。Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,不过在 JDK 1.5 之后随着 Java. util. concurrent 并发包的出现,它们也有了自己对应的线程安全类,比如 HashMap 对应的线程安全类就是 ConcurrentHashMap。
2、Stack 提供 5 个额外的方法使得可以以被当作堆栈/队列一样使用:
1)基本的 push 和 pop 方法 2)还有 peek 方法得到栈顶的元素 3)empty 方法测试堆栈是否为空 4)search 方法检测一个元素在堆栈中的位置 |
3、首次创建堆栈时,它不包含项,为空栈。
public class Stack<E> extends Vector<E> {
//...查看堆栈顶部的对象,但不从堆栈中移除它。 public synchronized E peek() {int len = size();if (len == 0)throw new EmptyStackException();return elementAt(len - 1);}
//...移除堆栈顶部的对象,并作为此函数的值返回该对象。 public synchronized E pop() {E obj;int len = size();obj = peek();removeElementAt(len - 1);return obj;}
//...回对象在堆栈中的位置,以 1 为基数。如果对象 o 是堆栈中的一个项,此方法返回距堆栈顶部最近的出
//现位置到堆栈顶部的距离;堆栈中最顶部项的距离为 1。使用 equals 方法比较 o 与堆栈中的项public synchronized int search(Object o) {int i = lastIndexOf(o);if (i >= 0) {return size() - i;}return -1;}
...
在线演示源码:src/main/java/org/example/collection/StackTest.java · 汪少棠/java-se - Gitee.com
CopyOnWriteArrayList
1、CopyOnWriteArrayList 是 ArrayList 的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。
2、如下所示为 CopyOnWriteArrayList 的 set 方法的源码,可以看出它是使用 Lock 接口进行上锁与解锁,其余可变操作同理。
3、这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法更 有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。
4、CopyOnWriteArrayList 允许使用所有元素,包括 null。
public class CopyOnWriteArrayList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {...//属性/** The lock protecting all mutators */final transient ReentrantLock lock = new ReentrantLock();/** The array, accessed only via getArray/setArray. */private transient volatile Object[] array;/*** Gets the array. Non-private so as to also be accessible* from CopyOnWriteArraySet class.*/final Object[] getArray() {return array;}/**Sets the array.*/final void setArray(Object[] a) {array = a;}...//为指定索引处设置值/*** Replaces the element at the specified position in this list with the* specified element.** @throws IndexOutOfBoundsException {@inheritDoc}*/public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();//线程上对象锁try {Object[] elements = getArray();//获取原来的数组E oldValue = get(elements, index);//获取指定索引处的元素if (oldValue != element) {int len = elements.length;//原数组的大小Object[] newElements = Arrays.copyOf(elements, len);//复制一个新数组newElements[index] = element;//新数组改变指定索引处的值setArray(newElements);//新数组替换原数组} else {// Not quite a no-op; ensures volatile write semanticssetArray(elements);//如果新指定的值与旧值相等,则不做修改}return oldValue;} finally {lock.unlock();//解锁}}
...
在线演示源码:src/main/java/org/example/collection/CopyOnWriteArrayListTest.java · 汪少棠/java-se - Gitee.com
集合遍历方式汇总
在线演示源码:https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/collection/ColleErgodic.javahttps://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/collection/List2Test.java
List 集合元素去重
src/main/java/org/example/collection/List2Test.java · 汪少棠/java-se - Gitee.com
https://gitee.com/wangmx1993/java-se/blob/master/src/main/java/org/example/collection/Person.java
Java SE 基础:List 集合列表相关推荐
- Java SE基础(十六)集合
Java SE基础(十六)集合 集合 集合体系 数据结构简述 栈 队列 数组 链表 Collection集合 List集合 ArrayList集合 LinkedList集合 Set集合 HashSet ...
- 面试必会系列 - 1.1 Java SE 基础
本文已收录至 github,完整图文:https://github.com/HanquanHq/MD-Notes Java SE 基础 面向对象 Java 按值调用还是引用调用? 按值调用指方法接收调 ...
- Java SE 基础知识
Java SE 基础知识 1 2 @(Notes)[J2SE, Notes] VICTORY LOVES PREPARATION. 特别说明: 该文档在马克飞象查阅最佳: 本部分知识还在迭代中,欢迎补 ...
- Java SE基础(更新中)
Java的运行机制 Java SE基础(更新中) 基本语法 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的. 类名:对于所有的类来说,类名的首字母应该大写 ...
- Java复习总结(二)Java SE基础知识
Java SE面试题 目录 Java SE基础 基本语法 数据类型 关键字 面向对象 集合 集合类概述 Collection接口 进阶 线程 锁 JDK 反射 JVM GC io操作和NIO,AIO ...
- JAVA SE基础知识总结
JAVA基础篇 1_JAVA语言概述 1.1 JAVA的总体概述 1.2 JAVA语言概述 1.2.1 基础常识 1.2.2 计算机语言的发展迭代史 1.2.3 Java语言版本迭代概述 1.2.4 ...
- java实现linkstring,【JAVA SE基础篇】32.String类入门
[JAVA SE基础篇]32.String类入门 1.字符串 1.String类又称作不可变字符序列 2.String位于java.lang包中,java程序默认导入java.lang包下所有的类 3 ...
- java 中间容器 表格_【JAVA SE基础篇】45.迭代器、Collections工具类以及使用容器存储表格...
本文将要为您介绍的是[JAVA SE基础篇]45.迭代器.Collections工具类以及使用容器存储表格,具体完成步骤: 1.迭代器 迭代器为我们提供了统一遍历容器(List/Map/Set)的方式 ...
- Java SE 基础(十)Java中的异常
Java SE 基础(十)Java中的异常 什么是异常 异常的处理 异常类 throw和throws 自定义异常 什么是异常 Java 中处理错误的一种机制,Java 中的错误大致分为两类,一类是编译 ...
- Java SE基础(十四)常用API
Java SE基础(十四)常用API 概述 Object类 构造方法 成员方法 toString()方法 equals(Object obj)方法 Arrays排序 Arrays类概述 Arrays成 ...
最新文章
- 调试 后台 ajax post 对应的php的方法
- pyqt5 输入确认_对PyQt5的输入对话框使用(QInputDialog)详解
- UI基础视图----UIImageView总结
- PyQt4编程之自定义插槽
- 生命周期 用户可以操作dom_React 生命周期的打怪升级之路
- 次小生成树(POJ1679/CDOJ1959)
- IHttpModule 与IHttpHandler的区别
- .NET Core 2.1 Preview 2发布 - April 10, 2018
- Hangfire项目实践分享
- 【C++对象模型】第一章 关于对象
- (进阶)LeetCode(119)——杨辉三角 II(JavaScript)
- 特征工程框架及技术要点
- python银行卡号生成器_python面向对象编程实例---银行账号
- epson LQ 600KIIH 针式打印机走纸问题
- 标识符,注释,常量,变量
- js监听鼠标的滚轮滚动事件
- NB-IoT和GSM概述
- IDEA使用技巧之教你一招:隐藏指定文件/文件夹
- html网页左侧背景,CSS设置html网页背景图片 CSS设置网页背景颜色
- 数据链路层点对点通信