8.4.1 Java 8改进的List接口和ListIterator接口
List
作为Collection
接口的子接口,当然可以使用Collection
接口里的全部方法。而且由于List
是有序集合,因此List
集合里增加了一些根据索引来操作集合元素的方法。
方法 |
描述 |
void add(int index, Object element) |
将元素element 插入到List 集合的index 处。 |
boolean addAll(int index, Collection c) |
将集合c所包含的所有元素都插入到List 集合的index 处 |
Object get(int index) |
返回集合index 索引处的元素。 |
int indexOf(Object o) |
返回对象o在List 集合中第一次出现的位置索引. |
int lastIndexOf(Object o) |
返回对象o在List 集合中最后一次出现的位置索. |
Object remove(int index) |
删除并返回 index 索引处的元素。 |
Object set(int index, Object element) |
将 index 索引处的元素替换成element 对象,返回被替换的旧元素。 |
List subList(int fromIndex, int tolndex) |
返回从索引 fromIndex (包含)到索引toIndex (不包含)处所有集合元素组成的子集合。subXxxx 方法一般遵循前闭后开 原则. |
所有的List 实现类都可以调用这些方法来操作集合元素。与Set 集合相比,List 增加了根据索引来插入、替换和删除集合元素的方法。除此之外,Java 8 还为List 接口添加了如下两个默认方法 |
|
方法 |
描述 |
void replaceAll(UnaryOperator operator) |
根据 operator 指定的计算规则重新设置List 集合的所有元素。 |
void sort(Comparator c) |
根据 Comparator 参数对List 集合的元素排序。 |
## List集合常规用法 ## |
|
下面程序示范了List 集合的常规用法。 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import java.util.*;
public class ListTest { 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); books.add(1 , new String("疯狂Ajax讲义")); for (int i = 0 ; i < books.size() ; i++ ) { System.out.println(books.get(i)); } books.remove(2); System.out.println(books); System.out.println(books.indexOf(new String("疯狂Ajax讲义"))); books.set(1, new String("疯狂Java讲义")); System.out.println(books); System.out.println(books.subList(1 , 2)); } }
|
|
|
List
集合可以根据位置索引来访问集合中的元素,因此List
增加了一种新的遍历集合元素的方法:使用普通的for
循环来遍历集合元素。运行上面程序,将看到如下运行结果:
1 2 3 4 5 6 7 8 9
| [轻量级Java EE企业应用实战, 疯狂Java讲义, 疯狂Android讲义] 轻量级Java EE企业应用实战 疯狂Ajax讲义 疯狂Java讲义 疯狂Android讲义 [轻量级Java EE企业应用实战, 疯狂Ajax讲义, 疯狂Android讲义] 1 [轻量级Java EE企业应用实战, 疯狂Java讲义, 疯狂Android讲义] [疯狂Java讲义]
|
从上面运行结果清楚地看出List
集合的用法。注意①行代码处,程序试图返回新字符串对象在List
集合中的位置,实际上List
集合中并未包含该字符串对象。因为List
集合添加字符串对象时,添加的是通过new
关键字创建的新字符串对象,①行代码处也是通过new
关键字创建的新字符串对象,两个字符串显然不是同一个对象,但List
的indexof
方法依然可以返回1。List
判断两个对象相等的标准是什么呢?
List如何判断两个对象相等
List
判断两个对象相等只要通过equals
方法比较返回true
即可。看下面程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.util.*;
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); books.remove(new A()); System.out.println(books); books.remove(new A()); System.out.println(books); } }
|
编译、运行上面程序,看到如下运行结果:
1 2 3
| [轻量级Java EE企业应用实战, 疯狂Java讲义, 疯狂Android讲义] [疯狂Java讲义, 疯狂Android讲义] [疯狂Android讲义]
|
从上面运行结果可以看出,执行①行代码时,程序试图删除一个A对象,List
将会调用该A对象的equals()
方法依次与集合元素进行比较,如果该equals()
方法以某个集合元素作为参数时返回true
,List
将会删除该元素。
由于A类重写了equals
方法,该方法总是返回true
。所以每次从List
集合中删除A对象时,总是删除List
集合中的第一个元素。
当调用List
的set(int index, Object element)
方法来更新List
集合指定索引处的元素时,指定的索引必须是List
集合的有效索引。例如集合长度是4,就不能指定替换索引为4处的元素—也就是说,set( int index, Object element)
方法不会改变List
集合的长度.
Java 8
为List
集合增加了sort()
和replaceAll()
两个常用的默认方法,其中
sort()
方法需要一个Comparator
对象来控制元素排序,程序可使用Lambda
表达式来作为参数;
而replaceAll()
方法则需要个UnaryOperator
来替换所有集合元素, UnaryOperator
也是一个函数式接口,因此程序也可使用Lambda
表达式作为参数。如下程序示范了List
集合的两个默认方法的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import java.util.*;
public class ListTest3 { 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讲义")); books.add(new String("疯狂iOS讲义")); books.sort((o1, o2)->((String)o1).length() - ((String)o2).length()); System.out.println(books); books.replaceAll(ele->((String)ele).length()); System.out.println(books); } }
|
1 2
| [疯狂iOS讲义, 疯狂Java讲义, 疯狂Android讲义, 轻量级Java EE企业应用实战] [7, 8, 11, 16]
|
上面程序中编号为①的代码控制对List
集合进行排序,传给sort()
方法的Lambda
表达式指定的排序规则是:字符串长度越长,字符串越大,因此执行完第一行粗体字代码之后,List
集合中的字符串按由短到长的顺序排列.
程序中编号为②的代码传给replaceAll()
方法的Lambda
表达式指定了替换集合元素的规则:直接用集合元素(字符串)的长度作为新的集合元素。执行该方法后,集合元素被替换为[7,8,11,16]
。
与Set
只提供了一个iterator()
方法不同,List
还额外提供了一个listIterator()
方法,该方法返回一个ListIterator
对象, ListIterator
接口继承了Iterator
接口,提供了专门操作List
的方法。 ListIterator
接口在Iterator
接口基础上增加了如下方法。
方法 |
描述 |
boolean hasPrevious() |
返回该迭代器关联的集合是否还有上一个元素。 |
Object previous() |
返回该迭代器的上一个元素. |
void add(Object o) |
在指定位置插入一个元素。 |
## ListIterator和Iterator的对比 ## |
|
- ListIterator 增加了向前迭代的功能,而Iterator 只能向后迭代 |
|
- ListIterator 可通过add() 方法向List 集合中添加元素,而Iterator 只能删除元素. |
|
下面程序示范了ListIterator
的用法.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.*;
public class ListIteratorTest { public static void main(String[] args) { String[] books = { "小明", "小王", "小张" }; List bookList = new ArrayList(); for (int i = 0; i < books.length; i++) { bookList.add(books[i]); } ListIterator lit = bookList.listIterator(); while (lit.hasNext()) { System.out.println(lit.next()); lit.add("小芳"); }
System.out.println("=======下面开始反向迭代======="); while (lit.hasPrevious()) { System.out.println(lit.previous()); } } }
|
从上面程序中可以看出,使用ListIterator
迭代List
集合时,开始也需要采用正向迭代,即先使用next()
方法进行迭代,在迭代过程中可以使用add()
方法向上一次迭代元素的后面添加一个新元素。运行上面程序,看到如下结果:
1 2 3 4 5 6 7 8 9 10
| 小明 小王 小张 =======下面开始反向迭代======= _小芳 小张 _小芳 小王 _小芳 小明
|
原文链接: 8.4.1 Java 8改进的List接口和ListIterator接口