集合-Collection接口

集合 和 数组 的比较:

             数组 - 本质上就是在内存空间中申请的一段连续内存空间,存放多个相同类型的数据

         - 数组一旦定义完毕,则在内存空间中的长度固定。

         - 插入/删除元素时可能导致大量元素的移动,因此效率比较低。

        - 使用数组下标访问元素非常便利。

        - 数组中的元素可以是基本数据类型,也可以是引用数据类型。

 

             集合  - 内存空间不一定连续,数据类型不一定相同。

         - 内存空间的长度不固定,可以动态调整。

         - 插入/删除元素时可以不移动大量元素,效率可以提高。

          - 不一定支持下标访问。

         - 集合中的所有元素都必须是引用数据类型,(如果硬是要放置基本数据类型,则借助包装类。)

  集合类 - 主要指用于描述集合的相关类和接口。
 

集合 主要分为两大类: Collection 接口Map接口

其中

Collection  接口中 存放元素的基本单位是  单元素   (单列集合)

        Map   接口中 存放元素的基本单位是   单元素   (双列集合)

Collection  接口本身很少使用,通常都是使用 子接口: List接口、Set接口、Queue接口

 


 

注意事项:

集合中只能存储引用类型;

集合之所以能够存放各种引用类型的数据,是因为:

都当做Object类型处理。(多态方式放置)

即,往集合中放入任何一个元素的时候,其实都是提升为一个Object类型,存储进集合中。


 一、Collection接口:


 


 

 常用方法:

boolean add(E e)                                        -用于将参数指定的元素放入当前集合中。若当前集合发生了更改,则返回true,否则返回false

 

boolean addAll(Collection<? extends E> c)    -用于将参数指定集合中的所有元素都增加到当前集合中;

 

boolean contains (Object o)                         -判断参数指定的元素是否在当前集合中

boolean containsAll(Collection<?>  c)           -判断参数指定集合中的所有元素是否在当前集合中

boolean remove(Object  o                          -用于删除参数指定的单个元素

boolean removeAll(Collection<?>  c)             -删除参数指定的所有元素

void clear()                                                   -用于清空当前的集合

 

boolean       isEmpty()      -判断当前集合是否为空

      int          size()           -用于获取当前集合中的元素个数

boolean       retainAll(Collection<?>  c)    -用于计算两个集合的交集

Iterator<E>  iterator()       -用于获取当前集合中的迭代器

 


 

 代码:

1.写一个Student类          (int id,String name)   这里省略不写了

2. 测试

package com.monkey1024;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest {

    public static void main(String[] args) {
        // new c1ollec1tion();  // 报错原因:c1ollec1tion是个接口,接口不能构造对象
        
        //c1ollec1tion接口的引用 指向 实现类的对象,形成多态
        Collection c1 = new ArrayList();
        
        // 向集合中,添加String类型的元素
        boolean b = c1.add("one");
        System.out.println("向c1集合中添加String类型的元素\"one\"是否成功: "+b);
        b = c1.add("one");
        System.out.println("再次向c1集合中添加一个String类型的元素\"one\"是否成功: "+b);
        
        // 向集合中添加int基本数据类型的数据为什么不报错?
        // 实现了自动装箱处理:int ===>  Integer类型
        c1.add(23);
        
        // 向集合中添加了Student类型的数据
        c1.add(new Student(1001,"James"));
        
        
        // 打印集合中的每个元素,自动调用toString()方法
        System.out.println("打印集合c1中的元素:"+c1);

        // 打印集合中元素的个数
        int num = c1.size();
        System.out.println("集合c1中元素个数: "+num);
        
        System.out.println();
        
         // 准备另一个新集合c2
         Collection c2 =new ArrayList();
         
         c2.add(3);
         c2.add("four");
         c2.add("two");
         
         // 查看c2集合
         System.out.println(c2);
         
         
         // 将当前c2集合中的所有元素都放入到c1集合中
         b = c1.addAll(c2);
         System.out.println("将当前c2集合中的所有元素都放入到c1集合中: "+b);
        System.out.println("打印c1集合:"+c1);
        System.out.println();
        
        
        // 判断c1集合中是否有元素"one"
        b = c1.contains("one");
        System.out.println("c1集合中是否有元素\"one\": "+b);
        
        
        // 判断集合是否存在的本质就是 调用了equals(),不重写该方法就比较对象的地址。
        b = c1.contains(new Student(1001,"James"));
        System.out.println("判断给集合中是否存在Student(1001,\"James\")对象: "+b);
        
        // 判断c1集合中是否包含c2集合
        b = c1.containsAll(c2);
        System.out.println("集合c1中是否包含集合c2: "+b);
        
        b = c2.add("5");
        System.out.println("集合c2中添加元素5: "+b);
        
        // 判断c1集合中是否包含c2集合
        b = c1.containsAll(c2);
        System.out.println("集合c1中是否包含集合c2: "+b);
        System.out.println();
        
        
        // 删除集合c1中的元素"one"
        b = c1.remove("one");
        System.out.println("删除集合c1中的元素\"one\": "+b);
        
        // 删除集合c1中的元素28
        b = c1.remove(28);
        System.out.println("删除集合c1中的元素28: "+b);
        
        // 删除集合c1中包含的集合c2
        b = c1.removeAll(c2);
        System.out.println("删除集合c1中包含的集合c2: "+b);
        
        // 清空集合c1中所有元素
        c1.clear();
        
        // 打印集合c1
        System.out.println("打印集合c1: "+c1);
        
        
        // 创建一个集合c3
        Collection c3 = new ArrayList();
        c3.add(23);
        c3.add(24);
        c3.add(25);
        
        // 创建一个集合c4
        Collection c4 = new ArrayList();
        c4.add(25);
        c4.add(26);
        c4.add(27);
        
        // 计算集合c3 和 集合 c4的交集,若有交集,则把交集部分保留在c3中,并且返回true。否则返回false
        b = c3.retainAll(c4);        
        System.out.println("集合c3和集合是否有交集: "+b);
        System.out.println("打印集合c3:"+c3);
        
        // 当集合自己和自己取交集时,则交集还是自己,自己不会发生改变,返回false
        b = c4.retainAll(c4);
        System.out.println("集合c4自己和自己取交集:"+b);
        System.out.println("打印集合c4:"+c4);
        
        // 清空集合c4中的元素
        c4.clear();
        
        // 判断集合c4是否为空集合
         b = c4.isEmpty();
         System.out.println("打印集合c4: "+c4);
         System.out.println("对集合c4进行了清空操作后,判断集合c4是否为空集合: "+b);

    }

}

结果:

向c1集合中添加String类型的元素"one"是否成功: true
再次向c1集合中添加一个String类型的元素"one"是否成功: true
打印集合c1中的元素:[one, one, 23, Student [name=James, id=1001]]
集合c1中元素个数: 4

[3, four, two]
将当前c2集合中的所有元素都放入到c1集合中: true
打印c1集合:[one, one, 23, Student [name=James, id=1001], 3, four, two]

c1集合中是否有元素"one": true
判断给集合中是否存在Student(1001,"James")对象: true
集合c1中是否包含集合c2: true
集合c2中添加元素5: true
集合c1中是否包含集合c2: false

删除集合c1中的元素"one": true
删除集合c1中的元素28: false
删除集合c1中包含的集合c2: true
打印集合c1: []
集合c3和集合是否有交集: true
打印集合c3:[25]
集合c4自己和自己取交集:false
打印集合c4:[25, 26, 27]
打印集合c4: []
对集合c4进行了清空操作后,判断集合c4是否为空集合: true

二、 List 接口

1.概述

java.util.List接口是Collection接口的子接口,继承自Collection接口。

该集合中的元素是有序的(放入次序,而非大小次序),允许有重复的元素存在。

该接口的主要实现类:ArrayList类、LinkedList类、Stack类、Vector类(笔试)

ArrayList类的底层       --- 动态数组 实现       访问 和 修改  方 便,  增删不方便;

LinkedList类的底层     --- 链     表        实现   访问 和 修改 不方便,增删方便;

Stack类的底层            --- 动态数组 实现       该类是一种具有后进先出特性的数据结构,简称LIFO [ last in first out ]  栈 ;

Vector类的底层           --- 动态数组 实现       与ArrayList类相比,支持线程安全,效率比较低。Java官方推荐使用ArrayList来取代它。

 

2.常用方法   (List接口中的方法包含了Collection接口中的方法)

void  add(int  index, E element)                                     -将数据element插入到 index指向的位置

boolean addAll(int  index,  Collection<? extends E>  c)     -将集合c中的所有元素插入到index指向的位置

remove(int  index)                                                  -删除index指向位置的元素,并返回该位置被删除的元素

E  set(int  index, E element)                                          -将index位置的元素替换为element,返回替换之前的元素值。  index的取值范围时:[ 0, size()-1 ]
get(int  index                                                        -返回index指向位置的元素值

List<E>  subList(int  fromIndex,  int  toIndex)                  -获取集合中下标从fromIndex(包含) 到toIndex(不包含)之间的所有元素

  

代码:

package com.monkey1024.collection;
import java.util.ArrayList; //List接口
import java.util.List;

import com.monkey1024.bean.Student;

public class ListTest { 
    
    public static void main(String[] args) {
        
        // 定义接口类型的引用,指向实现类的对象 形成多态
        List l1=new ArrayList();
        
        // 操作1:向集合中添加元素
        l1.add("one");
        l1.add(123);
        l1.add(new Student(29,"郜林"));
        l1.add(123);
        
        // 操作2:向指定的下标位置 插入元素 (索引的方式)
        l1.add(0, "first");
        l1.add(2,2019);
        System.out.println("打印集合l1: "+l1);
        System.out.println();
        
        // l1.add(9,2019);  报数组下标越界异常
        System.out.println(l1);
        
        // 操作3:将l2集合中的所有元素 插入到l1集合中 下标为1的位置
        List l2 =new ArrayList();
        l2.add("two");
        l2.add(1001);
        l2.add(new Student(23,"迪亚曼蒂"));
        l2.add(1001);
        boolean b = l1.addAll(1, l2);
        System.out.println("将l2集合中的所有元素 插入到l1集合中 下标为1的位置: "+b);
        System.out.println("打印集合l1: "+l1);
        System.out.println("");
        
        // 操作4:获取 l1集合中下标为 3的元素
        
         
        //String str = (String) l1.get(3);  // error 报错原因:所有放入元素都是object类型放入的
        //System.out.println(str);
        
        //解决方案:做判断    //不论元素是以什么类型存入集合中的,从集合中取出的元素都是Object类型
        Object obj = l1.get(3);
        
        if(obj instanceof String ) {
            String str = (String)obj;
            System.out.println("打印集合l1中下标为3的元素: l1[3] ="+str);
        }else {
            System.out.println(obj);
            
        }
        System.out.println( );
        
        // 操作5:获取l1集合中的所有元素值 (要求每个元素单独占一行)
        System.out.println("获取l1集合中的所有元素值 (要求每个元素单独占一行):");
     for(int i=0;i<l1.size();i++) {
         
        // 获取集合中的每一个元素
         System.out.println(l1.get(i));
         
     }
         System.out.println( );
         
        // 操作6:删除 l1集合中,下标为2的元素
     
         Object remove = l1.remove(2);
         System.out.println("打印被删除的数据值: "+remove); //返回值是 被删除的数据值
         System.out.println();
         
         
         //操作7: 将l1集合中下标为1的元素 改为 "two"
         obj=l1.set(1, "what");
         System.out.println(obj); //返回值是 修改之前的数据值  two
         System.out.println( );
         
         // 操作8:获取 链表中 指定区间位置的所有元素 (操作的是同一块内存空间)
         List l3 = l1.subList(1, 4);       //从索引1开始,但是不包含索引4
         System.out.println("打印l3: "+l3);
         System.out.println( );
         
         // 操作9:泛型的使用
         //限制了该集合中 只能存放String类型
         List<String> l4 = new ArrayList<String> ();
         
         l4.add("霍霍托夫斯基");
         // l4.add(111);  报错  111是int类型
         // l4.add(new Student(07,"C罗"));  报错 这是 Student类型
        System.out.println(l4);
         
        
        
    }
}

结果:

打印集合l1: [first, one, 2019, 123, Student[id=29,name+郜林], 123]

[first, one, 2019, 123, Student[id=29,name+郜林], 123]
将l2集合中的所有元素 插入到l1集合中 下标为1的位置: true
打印集合l1: [first, two, 1001, Student[id=23,name+迪亚曼蒂], 1001, one, 2019, 123, Student[id=29,name+郜林], 123]

Student[id=23,name+迪亚曼蒂]

获取l1集合中的所有元素值 (要求每个元素单独占一行):
first
two
1001
Student[id=23,name+迪亚曼蒂]
1001
one
2019
123
Student[id=29,name+郜林]
123

打印被删除的数据值: 1001

two

[what, Student[id=23,name+迪亚曼蒂], 1001]

[霍霍托夫斯基]

 


 

三、Queue 接口

1.概述
java.util.Queue接口是Collection接口的子接口,与List接口和Set接口是平级关系;
Queue接口,具有 先进先出 的特性;【队列】
 
Queue接口的 常用子接口有: Deque接口,表双端队列;
Queue接口的 常用实现类有: LinkedList类,增删方便,查改不便;
 
2. 栈 和 队列 的比较:
【栈】 LIFO(last in first out) : 具有 后进先出特性的数据结构。
【队列】FIFO(first in first out) : 具有先进先出特性的数据结构。
 
3. 常用方法:
boolean offer (E e) -用于将参数指定的数据插入到队列中。
E peek ( ) -用于获取队列的首元素值,若队列为空,则返回null;
E poll ( ) -获取并移除此队列的头,如果此队列为空,则返回null
 
4.代码伺候:
import java.util.LinkedList;
import java.util.Queue;

public class TestQueue {

    public static void main(String[] args) {
        
        // 定义一个 Queue接口类型的引用指向 实现类的对象,形成了多态
        // 使用了泛型,规定该集合类只能存储Integer类型的元素
        Queue<Integer> q1 =new LinkedList<Integer>();
        
        // 操作1:向集合中添加元素
        for(int i=1;i<7;i++) {
            q1.offer(i*10+i);
            
        }
        System.out.println("1.打印集合q1的元素: "+q1);
        
        // 操作2:获取队列中首元素值 并且打印
        Integer peek = q1.peek();
        System.out.println("2.获取队列中首元素值: "+peek);
        
        // 操作3: 删除集合中的元素
        
        for(int i=1;i<7;i++) {
            System.out.println("3.执行了:删除集合q1中的元素 "+q1.poll());
        }
        
        // 操作4:获取队列中首元素并打印
        peek = q1.peek();
        System.out.println("4.获取队列中首元素并打印: "+peek);

    }

}

 结果:

1.打印集合q1的元素: [11, 22, 33, 44, 55, 66]
2.获取队列中首元素值: 11
3.执行了:删除集合q1中的元素11
3.执行了:删除集合q1中的元素22
3.执行了:删除集合q1中的元素33
3.执行了:删除集合q1中的元素44
3.执行了:删除集合q1中的元素55
3.执行了:删除集合q1中的元素66
4.获取队列中首元素并打印: null

 

 
 

四、Set 接 口
1、概述
java.util.Set接口,是Collection 接口的子接口。与List,Queue接口属于平级关系;
该集合中的元素是无序的 (无放入次序,并不是大小顺序),不允许有重复的元素。
Set接口的主要实现类: HashSet类 和 TreeSet类
 
HashSet类 :底层采用的是 哈希表 进行数据管理;
TreeSet类 : 底层采用的是 二叉树 进行数据管理;
 
2、 常用方法 (该接口中的方法和Collection接口中的方法一样)
Iterator<E> iterator( ) -用于获取当前集合中的迭代器,用于遍历集合中所有元素。
 

 

代码:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class TestSet {

    public static void main(String[] args) {
         // 定义一个Set类型的接口 的引用 指向 实现类的对象 形成多态
        Set<String> s1 =new HashSet<String> (); 
        
        // 往 集合中添加元素
        
        s1.add("one");
        s1.add("two");
        s1.add("three");
        
        // 操作1: 添加重复的元素
        boolean b = s1.add("one");
        System.out.println("1.添加重复的元素能否成功:"+b);   // 返回false 重复的元素添加失败
        System.out.println();
        
        // 操作2: 打印集合中的所有元素,整体 返回字符串,操作不够灵活
        System.out.println("2.打印集合s1: "+s1);
        System.out.println();
        
        // 操作3: 使用迭代器打印集合中的元素
        // 获取 迭代器对象
        Iterator<String> it = s1.iterator();
        
        // 判断是否有可以 迭代的元素,有则取出并打印
        
        while(it.hasNext()) {
            String str = it.next();
            System.out.println("3.使用迭代器打印集合中的元素: "+str);
            
        }
        
            // 操作4: 删除集合中的元素two
            s1.remove("two");
            System.out.println("4.删除元素two之后的s1集合:"+s1);
             
            // 重新获取集合中的迭代器!!!!
            it=s1.iterator();
        
            // 操作5:将集合中使用 "t" 开头的元素 找到并删除
            while(it.hasNext()) {
                if(it.next().startsWith("t")) {
                
           // 引发对象并发修改异常,集合在迭代的过程中不允许修改
               // s1.remove(it.next());        // 引发对象并发修改异常,因为集合在迭代的过程中不允许修改
                    it.remove();  // 只能用迭代器自己的remove()方法来删除刚刚遍历的元素
            }
        }System.out.println("5.打印集合s1: "+s1);
        
    }

}
结果:
 
1.添加重复的元素能否成功:false

2.打印集合s1: [one, two, three]

3.使用迭代器打印集合中的元素: one
3.使用迭代器打印集合中的元素: two
3.使用迭代器打印集合中的元素: three
4.删除元素two之后的s1集合:[one, three]
5.打印集合s1: [one]
 
注意这行代码:
it = s1.iterator(); // 重新获取集合中的迭代器!!!!
 
原因:上一个迭代器的指针已经走到了集合的末尾。重新获取新的迭代器,是让迭代器的指针回到集合的开头。
 

 


4、元素放入 HashSet类的过程
(1)调用放入元素的hashCode()方法,得到该元素的哈希码值;
(2)通过哈希算法算出该元素在哈希表中的索引位置;
(3)若该索引位置没有元素,则将该元素直接放入到该索引位置上;
(4)若该索引位置有元素,则调用equals()方法,与已经存在的元素依次进行比较;
(5)若相等,则放弃该元素的插入。即,保留旧的,丢弃新的。(因为Set集合中不允许相同的元素重复)
若不相等,则将该元素插入到最后的位置。
 

 

这就是,重写equals()方法就得重写hashCode()方法的原因
 

5、元素放入TreeSet类的过程: (二叉树)
当向TreeSet类中放入元素时,需要指定元素的比较规则
 
指定方式有 2种:
方式A: 让元素类型实现Java.lang.Comparable 接口, 重写comparTo()方法,自然排序;
方式B: 在创建集合中,传入java.util.Comparator对象,重写compar()方法, 自定义比较器;
 
 
二叉树:
指的是 每个节点最多拥有两个子节点的树形结构,即,最多有两个分叉
 
 
 
 
有序二叉树:需要满足下列的三个特征:
(1)要求左子树中所有的节点必须小于根节点;
(2)要求右子树中所以的节点必须大于根节点;
(3)左右子树内部还得同时满足上述规则;
 
 
 
 
 
 
 
 
 
 
平衡二叉树:
左右子树高度差的绝对值不超过1的二叉树;(TreeSet类的底层就是一颗平衡有序二叉树)

 

代码:

package com.monkey1024.collection;

import java.util.Iterator;
import java.util.TreeSet;

public class TestTreeSet {

    public static void main(String[] args) {
        // 定义接口类型的引用 指向 实现类的对象,形成多态
        TreeSet<Integer> s1 = new TreeSet<Integer> ();
        
        // 增加元素到集合中
        s1.add(30);
        s1.add(10);
        s1.add(20);
        
        // 要求:打印集合中的所有元素  
        // 有3种方式:  
        // toString()、迭代器、foreach
        
        // 01.按照升序方式打印 (中序遍历方式)
        System.out.println("1.按照升序方式打印: "+s1);
        System.out.println();
        
        // 02.使用迭代器打印
        Iterator<Integer> iterator = s1.iterator(); // 获得迭代器对象
        while(iterator.hasNext()){  // 判断该集合有无可迭代的元素
            
            Integer next = iterator.next();
            System.out.println("2.使用迭代器打印:"+next);
            
        }
        
        System.out.println();
        
         // 03.使用foreach(增强for循环) 打印
        for (Integer it : s1) {
            System.out.println("3.使用foreach打印: "+it);
            
        }

    }

}

 

 结果:

1.按照升序方式打印: [10, 20, 30]

2.使用迭代器打印:10
2.使用迭代器打印:20
2.使用迭代器打印:30

3.使用foreach打印: 10
3.使用foreach打印: 20
3.使用foreach打印: 30

 

 练习:

自定义一个Student类实现封装;

在StudentTest测试类中定义TreeSet集合,并且向该集合中放入3个学生信息打印结果

 1.Student类

package com.moneky1024;

public  class Student implements Comparable<Student>{
    
    private int id ;
    private String name;
    
    public Student(int id, String name) {
        super();
         setId(id);
         setName(name);
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        
        if(id>0){
            this.id = id;
        }else {
            System.out.println("学号不合理.......");
        }
        
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (id != other.id)
            return false;
        return true;
    }
    
    
    // 实现了Comparable<String>接口,则必须重写compareTo(String o)方法
    public int compareTo(Student o) {
        // 按照学号比较大小
        //return getId()-o.getId();
        
        // 按照姓名比较大小
        // 调用compareTo()方法,  属性name 跟 参数name 比较
        return getName().compareTo(o.getName());
        
    }

    

}

 

 测试类

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

public class Test {

    public static void main(String[] args) {
        
        Set<Student> s = new TreeSet<Student>();
        
        // 向集合s 中添加3个学生信息
        s.add(new Student(1001,"Mary"));
        s.add(new Student(1002,"Bon"));
        s.add(new Student(1003,"Wide"));
        
     
        
        for (Student stu : s) {
            System.out.println("按照姓名进行排序打印:"+stu);
            
        }
        
        
        System.out.println("------------------------------------------------");
        
        // 先自定义比较器,使用 比较器指定的规则进行排序。那么使用有参的构造方法
        Set<Student> s2 = new TreeSet<Student>(new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                
                // 按照学号比较元素大小
                return o1.getId()-o2.getId();
            }
        });
        
        s2.add(new Student(1001,"Mary"));
        s2.add(new Student(1002,"Bon"));
        s2.add(new Student(1003,"Wide"));
        
        for (Student stu2 : s2) {
            System.out.println("按照学号进行排序的结果: "+stu2);   // 按照学号进行排序的结果
            
        }
        
        System.out.println("--------------------------------------------------");
        
        Set<Student> s3 = new TreeSet<Student>(new Comparator<Student>() {

            @Override
            public int compare(Student o1, Student o2) {
                // 按照姓名比较元素的大小
                return o1.getName().compareTo(o2.getName());
            }
        });
        
        s3.add(new Student(1001,"Mary"));
        s3.add(new Student(1002,"Bon"));
        s3.add(new Student(1003,"Wide"));
        
        for (Student student : s3) {
            System.out.println("按照姓名比较元素的大小: "+student);
            
        }
        

    }

}

 

 显示结果:

按照姓名进行排序打印:Student [id=1002, name=Bon]
按照姓名进行排序打印:Student [id=1001, name=Mary]
按照姓名进行排序打印:Student [id=1003, name=Wide]
------------------------------------------------
按照学号进行排序的结果: Student [id=1001, name=Mary]
按照学号进行排序的结果: Student [id=1002, name=Bon]
按照学号进行排序的结果: Student [id=1003, name=Wide]
--------------------------------------------------
按照姓名比较元素的大小: Student [id=1002, name=Bon]
按照姓名比较元素的大小: Student [id=1001, name=Mary]
按照姓名比较元素的大小: Student [id=1003, name=Wide]

 

 


 

五、迭代器的使用 ( 遍历 )

 

boolean hasNext() -判断集合中是否有可以迭代的元素,若有则返回true

 

E next() -获取集合中的一个元素,并且指向下一个元素

 

void remove() -用于删除迭代的一个元素

 

 

 

注意:

 

使用迭代器遍历集合中的元素时,不允许调用集合中的方法进行删除元素,只能通过迭代器自己的remove()进行元素的删除。否则引发对象并发修改异常。

 

  (ConcurrentModificationException)

 

 

 

  代码:

 

package com.monkey1024;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test {

    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add(11);
        c.add(22);
        c.add(33);
        c.add(44);
        
        Iterator it = c.iterator();
        
        while(it.hasNext()) {
            
            Object obj = it.next();
            if(obj.equals(22)) {
                
                // c.remove(obj); //报错:并发修改异常
                
                // 在迭代器中删除元素,要使用迭代器自己的 remove()方法进行删除!!!
                // 否则发生并发修改异常
                it.remove();    
            }
            
        }
        
        System.err.println("打印删除元素22之后的集合c: "+c);

    }

}

 

 结果:

打印删除元素22之后的集合c: [11, 33, 44]

 


 

 六、增强版 for循环 (for each)

 

for each 结构,也叫增强版for循环,是迭代器的简化版。
所以,能用迭代器遍历的集合,就能用 for each结构遍历。

 

1.语法格式:

for (元素类型 变量名 : 数组名或集合名){

循环体,使用变量名代表当前元素;

}

 

2.执行流程:

  1. 先声明元素类型的变量;
  2. 从数组或集合中取出元素赋值给变量
  3. 执行循环体
  4. 取出下一个元素赋值给变量
  5. 执行循环体
  6. ...............
  7. 元素取完为止

3.经验总结:

  • 在以后的开发中,若只是遍历集合中的所有元素,则推荐使用for each循环结构;
  • 在以后的开发中,若遍历集合的同时 还希望删除元素,则推荐使用迭代器结构。切记,调用的是迭代器自己的remove()方法,而不能是 集合的remove()方法。否则会产生并发修改异常。

集合的遍历方式:3种

01.toString()

02.迭代器

03.for each

对于 List 这种集合,还有get()这种方法可以遍历集合。


 七、泛型机制

 

 


 

八、Collections类

java.util.Collections类是Java官方提供的一个工具类,该类提供了大量针对集合中元素操作的方法。如max()获取集合中最大值。

 

 

 

 

 

 

posted @ 2019-10-28 00:03  小茅棚  阅读(219)  评论(0)    收藏  举报