System.out.println(books);
//将books集合的第二个元素(包括)
//到第三个元素(不包括)截取成子集合
System.out.println(books.subList(1 , 2));
}
}
运行结果:
①行代码处,程序试图返回新字符串对象在 List集合中的位置,实际上 List 集合中并未包含该字符串对象 。 因为 List 集合添加宇符串对象时 ,添加的是通过 new 关键宇创建的新字符串对象,①行代码处也是通过 new 关键宇创建的新字符串对象,两个字符串显然不是同一个对象,但 List 的 indexOf 方法依然可以返回 1 。
List 判断两个对象相等只要通过 equals()方法比较返回 true 即可 。
ListTest2.java
class A
{
public boolean equals(Object obj)
{
return true;
}
}
public class ListTest2
{
public static void main(String[] args)
{
List books = new ArrayList();
books.add(new String(“轻量级Java EE企业应用实战”));
books.add(new String(“疯狂Java讲义”));
books.add(new String(“疯狂Android讲义”));
System.out.println(books);
// 删除集合中A对象,将导致第一个元素被删除
books.remove(new A()); // ①
System.out.println(books);
// 删除集合中A对象,再次删除集合中第一个元素
books.remove(new A()); // ②
System.out.println(books);
}
}
运行结果:
执行①行代码时 ,程序试图删除一个 A 对象 , List 将会调用该A对象的equals()方法依次与集合元素进行比较,如果该 equalsO方法 以某个集合元素作为参数时返回 true , List将会删除该元素——A 类重写了 equalsO方法 , 该方法总是返回 true。所 以每次从 List 集合中删除 A 对象时 ,总是删除 List 集合中的第一个元素 。
与 Set 只提供了 一个 iterator()方法不同, List 还额外提供了 一个 listIterator()方法,该方法返回 一个Listlterator 对象, ListIterator 接口继承了Iterator 接口,提供了专门操作 List 的方法 。 ListIterator 接口在Iterator 接口基础上增加了如下方法 。
-
boolean hasPreviousO: 返回该法代器关联的集合是否还有上一个元素 。
-
Object previous(): 返回该迭代器的上一个元素。
-
void add(Object 0): 在指定位置插入一个元素 。
API:java.util.List
========================================================================================
ArrayList结构图
ArrayList 和 Vector 类都是基于数组实现的 List 类,所以 ArrayList 和 Vector 类封装了一个动态的、允许再分配的 Object[]数组 。 ArrayList 或 Vector 对象使用 initialCapacity 参数来设置该数组的长度, 当向 ArrayList 或 Vector 中添加元素超出了该数组的长度时,它们的 initialCapacity 会自动增加 。
ArrayList构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 如果传入的初始容量大于0,就新建一个数组存储元素
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 如果传入的初始容量等于0,使用空数组EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 如果传入的初始容量小于0,抛出异常
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
对于通常的编程场景,程序员无须关心 ArrayList 或 Vector 的 initialCapacity 。 但如果向ArrayList或 Vector 集合中添加大 量 元素时,可使用ensureCapacity(int minCapacity) 方法一次性地增加initialCapacity 。 这可以减少重分配 的 次数 ,从而提高性能 。
如果开始就知道 ArrayList 或 Vector 集合需要保存多少个元素,则可以在创建它们时就指定initialCapacity 大小 。 如果创建空的 ArrayList 或 Vector 集合时不指定 initialCapacity 参数 ,则 Object[] 数组的长度默认为 10 。
ArrayList属性
/**
- 默认容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
- 空数组,如果传入的容量为0时使用
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
- 空数组,传传入容量时使用,添加第一个元素的时候会重新初始为默认容量大小
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
- 存储元素的数组
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
- 集合中元素的个数
*/
private int size;
除此之外,ArrayList 和 Vector 还提供了如下两个方法来重新分配 Object[]数组:
-
void ensureCapacity(int minCapacity): 将 ArrayList 或 Vector 集合的 Object[]数组长度增加大于或等于 minCapacity 值。
-
void trimToSize(): 调整 ArrayList 或 Vector 集合 的 Object[]数组长度为 当前元素 的个数 。 调用该方法可减少 ArrayList 或 Vector 集合对象占用 的存储空间 。
ArrayList 和 Vector 在用法上几乎完全相同 ,Vector十分古老,那时候 Java 还没有提供系统的集合框架,所以 Vector 里提供了 一 些方法名很长的方法。
除此之外, ArrayList 和 Vector 的 显著区别是 :
ArrayList 是线程不安全的,当多个线程访问同一个ArrayList 集合时,如果有超过一个线程修改了 ArrayList 集合,则程序必须于动保证该集合的同步性;
但 Vector 集合则是线程安全的,无须程序保证该集合的同步性。因为 Vector 是线程安全的,所以 Vector的性能比 ArrayList 的性能要低 。
API:java.util.Vector
================================================================================
LinkedList结构图
LinkedList 类是 List 接口的实现类 一它是一 个 List 集合 ,可以根据索引来随机访问集合中的元素 。
除此之外, LinkedList 还实现了 Deque 接口,可以被当成双端队列来使用,还可以被当成"栈"来使用 。
下面程序简单示范了 LinkedList 集合的用法:
LinkedListTest.java
public class LinkedListTest
{
public static void main(String[] args)
{
LinkedList books = new LinkedList();
// 将字符串元素加入队列的尾部
books.offer(“疯狂Java讲义”);
// 将一个字符串元素加入栈的顶部
books.push(“轻量级Java EE企业应用实战”);
// 将字符串元素添加到队列的头部(相当于栈的顶部)
books.offerFirst(“疯狂Android讲义”);
// 以List的方式(按索引访问的方式)来遍历集合元素
for (int i = 0; i < books.size() ; i++ )
{
System.out.println(“遍历中:” + books.get(i));
}
// 访问、并不删除栈顶的元素
System.out.println(books.peekFirst());
// 访问、并不删除队列的最后一个元素
System.out.println(books.peekLast());
// 将栈顶的元素弹出“栈”
System.out.println(books.pop());
// 下面输出将看到队列中第一个元素被删除
System.out.println(books);
// 访问、并删除队列的最后一个元素
System.out.println(books.pollLast());
// 下面输出:[轻量级Java EE企业应用实战]
System.out.println(books);
}
}
LinkedList 与 ArrayList 的实现机制完全不同:
-
ArrayList 内部以数组的形式来保存集合中的元素 , 因此随机访问集合元素时有较好的性能;
-
而 LinkedList 内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能比较出色(只需改变指针所指的地址即可)。
双向链表