List集合
特点
- List集合支持修改方法,该方法Collection不具备。
- List集合中元素按存取顺序存储,即保持存取顺序。
- List集合是自带索引的,所以除了迭代器获取元素方法外,还可以使用遍历+get(int index)方法来获取元素。
- List集合元素可重复。
继承关系
Collection
|--List
|--ArrayList:数组结构,非线程安全,查询较快,增删较慢。
|--LinkedList:双向链表结构,非线程安全,增删较快,查询较慢(按序号索引数据需要进行向前或向后遍历)。
|--Vector:数组结构,线程安全,效率较低,已被ArrayList替代。
|--Stack:栈
常用方法
- 插入元素
void add(int index, E element)
boolean addAll(int index, Collection<? extends E> c) - 按索引获取元素
E get(int index) - 获取指定元素的索引
int indexOf(Object o)
int lastIndexOf(Object o) - 获取ListIterator迭代器
ListIterator<E> listIterator() - 按索引删除元素
E remove(int index) - 修改元素
E set(int index, E element) - 对元素排序,需要元素实现Comparator接口以具有可比性
default void sort(Comparator<? super E> c) - 按索引获取子集合
List<E> subList(int fromIndex, int toIndex)
示例
Person.java
package bean;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name .hashCode());
return result;
}
@Override
public boolean equals(Object obj ) {
if (this == obj) return true ;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false ;
Person other = (Person) obj;
if (age != other.age) return false;
if (name == null) {
if (other.name != null) return false;
} else if (!name.equals(other.name)) return false;
return true;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]" ;
}
}
ListDemo.java
package Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import bean.Person;
public class ListDemo {
public static void main(String[] args) {
List<Person> list = new ArrayList<Person>();
list.add(new Person( "Jacob" , 25));
list.add(new Person( "Meteor" , 24));
list.add(new Person( "Rose" , 23));
list.add(new Person( "Jacob" , 25));
// 判断重复,取决于元素类型中的equals()方法,并非是对象的引用是否一致。
printList(list );
// 1. 添加元素。
list.add(new Person( "Jacob" , 25));
// 2. 插入元素。
list.add(2, new Person( "hanlin" , 26));
// 3. 删除元素。
list.remove(4); // throws IndexOutOfBoundsException
// 4. 修改元素。
list.set(1, new Person( "Jacoblx" , 25));
printList(list );
removeSameElements(list );
printList(list );
}
public static void removeSameElements(List<Person> list ) {
/*
* 移除集合中的重复元素。
* 额外建立一个集合,将不重复的元素放到这个集合中,然后原集合清空并将该集合元素再全部加入到原集合中即可。
*/
List<Person> single = new ArrayList<Person>();
for (Iterator<Person> it = list.iterator(); it .hasNext();) {
Person temp = it.next();
if (!single.contains( temp)) {
single.add( temp);
}
}
list.clear();
list.addAll(single);
}
private static void printList(List<Person> list) {
for (Person person : list) {
System.out.println( person);
}
System.out.println( "-----------------------" );
}
}
运行结果
Person [name=Jacob, age=25]
Person [name=Meteor, age=24]
Person [name=Rose, age=23]
Person [name=Jacob, age=25]
-----------------------
Person [name=Jacob, age=25]
Person [name=Jacoblx, age=25]
Person [name=hanlin, age=26]
Person [name=Rose, age=23]
Person [name=Jacob, age=25]
-----------------------
Person [name=Jacob, age=25]
Person [name=Jacoblx, age=25]
Person [name=hanlin, age=26]
Person [name=Rose, age=23]
-----------------------
非迭代器遍历
List c = new ArrayList ();
b = c.add( "Java1");
b = c.add( "Java2");
b = c.add( "Java3");
for (int i = 0; i < c.size(); i++) {
String str = (String) c.get( i);
System.out.println( str + " ");
}
ListIterator迭代器
常用方法
- 添加元素
void add(E e) - 判断集合中是否有下一个元素
boolean hasNext() - 判断集合中是否有上一个元素
boolean hasPrevious() - 获取下一个元素
E next() - 获取下一个元素的索引
int nextIndex() - 获取上一个元素
E previous() - 获取上一个元素的索引
int previousIndex() - 移除元素
void remove() - 修改元素
void set(E e)
注意
- Iterator迭代器中只有获取方法,没有增删改方法。而ListIterator支持增删改操作,并支持向前遍历。
- 在迭代过程中,使用了集合的方法对元素进行操作,导致迭代器并不知道集合中的变化,引发数据的不确定性。
例如
for (Iterator it = list.iterator(); it.hasNext();) {
if ("heima2".equals(it.next())) {
list.add("java");
}
}
报java.util.ConcurrentModificationException异常。所以在迭代时,不要使用集合的方法操作元素,可以使用迭代器的方法操作。ListIterator支持增删改可以解决该问题。
注意:该列表迭代器只有List接口有,而且这个迭代器可以完成在迭代过程中的增删改查动作。 - 迭代过程中,增删改动作最多只能有1个,不可以两个同时进行。否则迭代器迭代序列可能出错,报java.lang.IllegalStateException异常。
示例
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class List_ListIterator {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Java1");
list.add("Java3");
list.add("Java2");
for (ListIterator<String> it = list.listIterator(); it.hasNext();) {
if ("Java3".equals( it.next())) {
it.add( "java");
// it.remove();
// it.set("Hello");
// 可以增删改查,但是不可两者同时。否则报java.lang.IllegalStateException异常
}
}
printList(list );
}
public static void printList(List<String> list) {
for (Iterator<String> it = list.iterator(); it.hasNext();) {
System.out.println( it.next());
}
}
}
ArrayList集合
特点
是List接口的实现类,用以替代Vector集合,并且具有比后者更高的效率,但是不保证线程安全。
注意
- List是接口,ArrayList是实现类。
- 一般使用多态的方式创建集合,如:
List<E> list = new ArrayList<E>();
这样使得集合具有更高的适用性。
LinkedList集合
特点
- 是List接口的实现类,双向链表结构,所以增删效率较高,可以用以实现队列或栈的数据结构。
- LinkedList动作特点均可以围绕头和尾展开。
队列实现
特点是先进先出FIFO数据结构,可以选择头插尾取,也可以选择尾插头取。
package collection.structure;
import java.util.LinkedList;
import java.util.ListIterator;
public class Queue<E> {
private LinkedList<E> link;
public Queue() {
link = new LinkedList<E>();
}
public boolean isEmpty() {
return link.isEmpty();
}
public void print() {
for (ListIterator<E> it = link.listIterator(link .size()); it .hasPrevious();) {
System.out.println( it.previous());
}
}
public void enQueue(E obj) {
link.addFirst( obj);
}
public E deQueue() {
return link.removeLast();
}
}
栈实现
特点是先进后出FILO数据结构,可以选择头插头取,也可以选择尾插尾取。
package collection.structure;
import java.util.LinkedList;
import java.util.ListIterator;
public class Stack<E> {
private LinkedList<E> link;
public Stack() {
link = new LinkedList<E>();
}
public boolean isEmpty() {
return link .isEmpty();
}
public void print() {
for (ListIterator<E> it = link.listIterator(link .size()); it .hasPrevious();) {
System. out.println(it .previous());
}
}
public void push(E obj) {
link.addFirst( obj);
}
public E pop() {
return link.removeFirst ();
}
}
程序调用
package collection;
import collection.structure.Queue;
import collection.structure.Stack;
public class List_LinkedList {
public static void main(String[] args) {
Queue<String> q = new Queue<String>();
Stack<String> s = new Stack<String>();
q.enQueue("q1");
q.enQueue("q2");
q.enQueue("q3");
s.push("s1");
s.push("s2");
s.push("s3");
System.out.println( "Queue:");
while (! q.isEmpty()) {
System.out.println( q.deQueue());
}
System.out.println( "------------------------");
System.out.println( "Stack:");
while (! s.isEmpty()) {
System.out.println( s.pop());
}
}
}
运行结果
Queue:
q1
q2
q3
------------------------
Stack:
s3
s2
s1
Vector集合
示例
package collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class List_Vector {
public static void main(String[] args) {
Vector<String> v = new Vector<String>();
// 添加元素
v.addElement("java1");
v.addElement("java2"); // 相当于无返回值的add(E e)
// 获取元素
String str1 = v.elementAt(1); // "java2",相当于v.get(1);
String str2 = v.firstElement(); // "java1"
String str3 = v.lastElement(); // "java2"
// 插入元素
v.insertElementAt( "java", 1);
// ["java1", "java", "java2"],相当于add( int index, E element)
// 移除元素
v.removeElement( "java"); // 相当于remove(Object o)
v.removeElementAt(1); // 相当于无返回值的remove( int index)
// 修改元素
v.setElementAt( "Hello Java", 0); // 相当于无返回值的set( int index, E element)
// 使用枚举遍历元素
for (Enumeration<String> en = v.elements(); en.hasMoreElements();) {
System.out.println( "enumeration: " + en.nextElement());
}
for (Iterator<String> it = v.iterator(); it.hasNext();) {
System.out.println( "iterator: " + it .next());
}
for (Object obj : v) {
System.out.println( "foreach iterator: " + obj );
}
}
}