黑马程序员-JAVA基础-Java 集合之List 集合

时间:2023-02-18 17:50:31

------- android培训java培训、期待与您交流! ----------

  List 接口是 Collection 的一个子接口。List 集合代表一个有序集合,集合中每个元素都是有其对应的顺序索引。List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。

 

一.List 接口:

  List 作为 Collection 的一个子接口,除了可以使用Collection 接口里的所有方法外,还有特有的一些方法:

  1、增加:

  void add(int index , Object element) : 在集合列表指定位置插入element 元素。

  boolean addAll(int index , Collection c) : 在集合列表指定位置插入一组数据。

  2、删除:

  Object remove(int index) : 删除并返回index 索引处的元素。

  3、修改:

  Object set(int index , Object element) : 将index 索引处的元素替代成element 对象,返回新元素。

  注意:所指定的索引index 必须是List 集合的有效索引,不能越界。如:集合长度为4 ,就不能指定索引为4 处的元素。

  4、查找:

  int indexOf(Object o) 返回对象o在List集合中出现的位置索引。

  int lastindexOf(Object o) 返回对象o 在List集合中最后一次出现的位置索引。

  Object get(int index) 返回集合index 索引处的元素。

  List subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间所有元素组成的子元素。 

 1 public class ListDamo {
 2     
 3     public static void main(String[] args)
 4     {
 5 //        创建List 子接口实现类对象
 6         ArrayList books = new ArrayList() ; 
 7         
 8 //        添加元素。
 9         books.add("诛仙1") ; 
10         books.add("诛仙2") ;
11         books.add("诛仙3") ;
12         books.add("诛仙4") ; 
13         ForeachMethod(books) ; 
14 //        在指定位置添加元素:
15         books.add(1 , "诛仙6") ;
16         books.add(2 , "诛仙7") ;
17         IteratorMethod(books) ; 
18 //        删除指定位置的元素:
19         books.remove(1)  ;
20         ForeachMethod(books) ;
21         
22         ArrayList books1 = new ArrayList() ; 
23         books1.add("笑傲江湖") ; 
24         books1.add("射雕英雄传") ; 
25         books1.add("神雕侠侣") ; 
26         
27 //        在指定位置添加一组元素:
28         books.addAll(1, books1) ;
29         IteratorMethod(books) ; 
30         
31 //        修改指定位置的元素:
32         books.set(5, "我修改了") ;
33         IteratorMethod(books) ; 
34         
35 //        返回指定元素:
36         System.out.println("get(1):"+ books.get(1));
37         
38     } 
39     public static void ForeachMethod(ArrayList books)
40     {
41         System.out.println("------我是foreach 遍历的结果------");
42 //        用foreach 遍历
43         for(Object obj : books)
44         {
45             String book = (String) obj ;
46             System.out.println(obj); 
47         }
48     }
49     public static void IteratorMethod(ArrayList books)
50     {
51         System.out.println("------我是Iterator 遍历的结果------");
52         Iterator it = books.iterator() ; 
53         while(it.hasNext())
54         {
55             String book = (String) it.next() ;
56             System.out.println(book);
57         }
58     }
59 }

 

  上面的遍历用了两种方法foreach 和 Iterator 迭代器。但其实List 集合有个特有的迭代器——ListIterator 。

二.ListIterator 接口

  ListIterator 接口是Iterator的子接口。但Iterator 接口中的方法有限只有判断(hasNext()),取出(next()),删除(remove())操作 。 而ListIterator 提供了专门操作List 的方法,ListIterator 接口在 Iterator 接口基础增加了如下方法:

  > boolean hasPrevious() ; 返回该迭代器关联的集合是否还有上一个元素。

  > Object previous() : 返回该迭代器的上一个元素。

  > void add() : 在指定位置上添加插入一个元素。

 1 public class ListIteratorText {
 2     public static void main(String[] args)
 3     {
 4         ArrayList books = new ArrayList() ; 
 5 //        添加元素:
 6         books.add("诛仙1") ; 
 7         books.add("诛仙2") ; 
 8         books.add("诛仙") ;
 9 //        用ListIterator 遍历
10         ListIterator li = books.listIterator() ; 
11 //        向后遍历
12         System.out.println("-------我是向后遍历-------");
13         while(li.hasNext())
14         {
15             String book = (String) li.next()  ;
16 //            如果li的下一个对象为"诛仙"这把它修改为"天龙八部" 
17             if(book.equals("诛仙")) 
18                 li.set("天龙八部") ; 
19 //            在每一个元素后面添加"----我是分割线---" 对象。
20             li.add("----我是分割线---") ;
21             System.out.println(book);
22         } 
23         System.out.println("-------我是向前遍历-------");
24 //        像前遍历
25         while(li.hasPrevious())
26         {
27             String book = (String) li.previous(); 
28             System.out.println(book);
29         } 
30     }
31 }

 

  注意:在迭代时,不可以通过集合对象的方法操作集合中的元素,只能用迭代器中的方法操作集合中的元素:增加、修改、删除。

  

三.LinkedList 实现类

  LinkedList 不仅实现了 List 接口,还实现了Queue 接口的子接口 Deque 接口, 其中Deque 接口 代表一个双向队列。所以,LinkedList 实现类底层的数据结构是链表,其特点是:增删很快,但查询稍慢。

  所以LinkedList 除了实现List 接口中所有方法外,还实现了 Deque 接口中的可以双向操作队列的方法:

  1、增加:

    void addFirst(Object o) ;将指定元素插入该双向队列的开头。  

    void addLast(Object o) ;将指定元素插入该双向队列的结尾:

  JDK 1.6 出现的方法: 

    boolean offerFirst(Object o ) ; 将指定元素插入该双向队列的开头 

    boolean offerLast(Object o) ;将指定元素插入该双向队列的结尾。

  2、删除: 

    removeFirst() ;  获取、并删除第一个元素,如果双端队列为空,则会出现NoSuchElementException异常

    removeLast() ;  获取、并删除最后一个元素,如果双端队列为空,则会出现NoSuchElementException异常

  JDK 1.6 出现的方法

    Object pollFirst() ;  获取、并删除第一个元素,如果双端队列为空,则会返回null

    Object pollLast() ;  获取、并删除最后一个元素,如果双端队列为空,则会返回null

  3、获取:

    Object getFirst() ; 获取、但不删除该队列的第一个元素。如果为空,将会出现NoSuchElementException异常

    Object getLast() : 获取、但不删除该队列的最后一个元素。如果为空,将会出现NoSuchElementException异常

  JDK 1.6 出现的方法

    Object peekFirst() : 获取、但不删除第一个元素,如果双端队列为空,则会返回null 。

    Object peekLast() : 获取、但不删除最后一个元素,如果双端队列为空,则会返回null 。

  所以,在创建LinkedList 实例后,应使用 JDK 1.6 出现的方法。

 1 public class LinkedListDemo {
 2     
 3     public static void main(String[] args)
 4     {
 5         LinkedList linkList = new LinkedList() ; 
 6 //        添加,全在链表队列头添加元素。
 7         linkList.addFirst("笑傲江湖01");
 8         linkList.addFirst("笑傲江湖02");
 9         linkList.addFirst("笑傲江湖03");
10         linkList.addFirst("笑傲江湖04");
11         System.out.println(linkList);
12 //        如果linkList 双向队列有最后一元素
13         while(linkList.peekLast()!= null)
14 //            获取并且删除最后一元素。
15             System.out.println(linkList.pollLast() ); 
16     }
17 }

  4、使用 LinkedList 模拟一个堆栈或者队列数据结构

   首先:堆栈是先进后出,队列是先进先出; 

 1 class StackDemo
 2 {
 3     private LinkedList stack  ; 
 4 //    构造函数。
 5     StackDemo()
 6     {
 7         stack = new LinkedList() ; 
 8     }
 9 //    添加方法
10     public void PushMethod(Object obj)
11     {
12         stack.offerFirst(obj) ; 
13     }
14 //    取出方法
15     public Object  PopMethod()
16     {
17         return stack.pollFirst() ; 
18     }
19 //    判断堆栈是不是为空
20     public boolean IsEmpty()
21     {
22         return stack.isEmpty() ; 
23     }
24 }
25 //模拟队列
26 class QueueDemo
27 {
28     private LinkedList stack  ; 
29 //    构造函数。
30     QueueDemo()
31     {
32         stack = new LinkedList() ; 
33     }
34 //    添加方法
35     public void PushMethod(Object obj)
36     {
37         stack.offerLast(obj) ; 
38     }
39 //    取出方法
40     public Object  PopMethod()
41     {
42         return stack.pollFirst() ; 
43     }
44 //    判断堆栈是不是为空
45     public boolean IsEmpty()
46     {
47         return stack.isEmpty() ; 
48     }
49 }

 

四. ArrayList 和 Vector 实现类

  ArrayList 和Vector 是List 接口的实现类,完全支持前面介绍的List 接口的全部功能。而且,两个实现类都是基于数组实现的List 类。

  ArrayList 和 Vector 类封装了一个动态再分配Object[] 数组。每个 ArrayList 和 Vector 对象有一个 capacity 属性(表示它们封装的Object[] 数组的长度),当向ArrayList 和Vector 对象中添加元素时,它们的capacity 会自动增加。 

  ArrayList 和Vector 类的区别:

  1、Vector 是一个很老的集合(JDK1.0) 就出现了;ArrayList 类是 (JDk 1.2 ) 出现的。所以 Vector 类中的方法名字很长,切很多方法重复。

  2、Vector 是线程安全的,而ArrayList 是线程不安全的。所以Vector 的性能比 ArrayList 的性能要低。而且Collections 工具类,可以将一个ArrayList 变成线程安全类。

  所以:尽量少用 Vector 类。

  练习 ArrayList :

  除去ArrayList 集合中的重复元素: 

 1     public static ArrayList SingleElement(ArrayList list)
 2     {
 3 //        创建新的ArrayList 对象。
 4         ArrayList alist = new ArrayList() ;
 5         
 6 //        遍历 list 实体。
 7         for(Object obj : list)
 8         {
 9 //            判断该对象在 alist 集合中是否存在。
10             if( !alist.contains(obj) )
11                     alist.add(obj) ; 
12         }
13         return alist ;
14     }

 

  不过,如果要判断一个对象是否相等要在对象类中重写Object 类中的equals() 方法。