List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引。
一、Java 8改进的List接口和ListIterator接口
List作为Collection接口的子接口,当然可以使用Collection接口里的全部方法。
而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法。
①void add(int index , Object element):将元素element插入到List集合的index处。
②boolean addAll(int index,Collection 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 toIndex):返回从索引fromIndex(包含)到toIndex(不包含)处所有集合元素组成的子集合。
所有的List实现类都可以调用这些方法来操作集合元素。与Set集合相比,List增加了根据索引来插入、替换和删除集合元素的方法。除此之外。Java 8 还为List接口添加了如下两个默认方法。
①void replaceAll(UnaryOperator operator):根据operator指定的计算规则重新设置List集合的所有元素
②void sort(Comparator c):根据Comparator参数对List集合的元素排序。
下面示范了List集合的常规用法。
import java.util.ArrayList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
List books = new ArrayList();
//向books集合中添加三个元素
books.add(new String("C Primer Plus"));
books.add(new String("C程序与设计"));
books.add(new String("Java编程"));
System.out.println(books);
//将新字符串对象插入在第二个位置
books.add(1,new String("Think In Java"));
for(int i = 0 ;i < books.size();i++)
{
System.out.println(books.get(i));
}
//删除第三个元素
books.remove(1);
System.out.println(books);
//判断指定元素在List集合中的位置,输出1,表明位与第二位
System.out.println(books.indexOf(new String("C程序与设计")));//①
//将第二个元素替换成新的字符串对象
books.set(1, new String("C++ Primer Plus"));
System.out.println(books);
//将books集合的第二个元素到第三个元素截取子集合
System.out.println(books.subList(1, 2));
}
}
上面程序中粗体字代码示范了List集合的独特用法,List集合可以根据位置索引来访问集合中的元素。因此List增加了一种新的遍历集合的元素的独特用法:使用普通的for循环来遍历集合元素。
在代码①行处,程序试图返回新字符串对象在List集合中的位置,实际上List集合添加字符串对象时,添加的是通过new关键字创建的新字符串对象,①行代码处也是通过new关键字创建的新字符串对象,两个字符串显然不是同一个对象,但List的indexOf方法依然可以返回1。List集合判断两个对象的标准是什么呢?List判断两个对象相等只要通过equals()方法比较返回true即可。
看下面程序。
import java.util.ArrayList;
import java.util.List;
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"));
books.add(new String("C"));
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);
}
}
运行结果
[Java, C, Android]
[C, 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()方法需要一个Compartor对象来控制元素排序,程序使用Lambda表达式来作为参数;而replaceAll()方法则需要一个UnaryOperator来替换所有集合元素,UnaryOperator也是一个函数式接口,因此程序也可使用Lambda表达式作为参数。
如下程序示范了List集合默认方法的功能。
import java.util.ArrayList;
import java.util.List;
public class ListTest3 {
public static void main(String[] args) {
List books = new ArrayList();
//向books集合中添加4个元素
books.add(new String("C"));
books.add(new String("Java"));
books.add(new String("C++"));
books.add(new String("C#"));
System.out.println(books);
//使用目标类型为Comparator的Lambda表达式对List集合排序
books.sort((o1,o2)-> ((String)o1).length() - ((String)o2).length());//①
System.out.println(books);
//使用目标类型为UnaryOperator的Lambda表达式来替换集合中的所有元素
//该Lambda表达式控制使用每个字符串的长度位新的集合元素
books.replaceAll(ele -> ((String)ele).length());//②
System.out.println(books);
}
}
上面程序①粗体字代码对List集合进行排序,传给sort()方法的Lambda表达式指定的排序规则是:字符串长度越长,字符串越大,因此执行完第一行粗体字代码之后,List集合中的字符串会按由短到长的顺序排列。