java 基础 迭代器Iterator 增强for循环 泛型

java.util.Collection接口
是集合的最顶层的接口,定义了集合共性的方法
接口无法直接创建对象,使用多态的方式创建对象
Collection<集合中的数据类型(泛型)> coll = new ArrayList<集合中的数据类型(泛型)>();

迭代器
集合中存储数据的方式(数据类型)不一样,取出集合中元素的方式也不同,java给我们提供了一种公共的取出元素的方式,叫迭代器
描述迭代器的接口:java.util.Iterator

接口中的抽象方法:
boolean hasNext() 如果仍有元素可以迭代,则返回 true。 判断集合中还有没有元素,有返回true,没有返回false
next() 返回迭代的下一个元素。 取出集合中的下一个元素

迭代器是一个接口,需要找到迭代器的实现类,迭代器的实现类是每个集合的内部类
在Collection接口中有一个方法: iterator方法返回的就是迭代器
Iterator<E> iterator() 返回在此 collection 的元素上进行迭代的迭代器。
ArrayList集合实现了Collection接口,重写iterator方法,方法的返回值就是迭代器的实现类对象

注意:我们只需要知道iterator方法返回的而是迭代器的实现类就行了,不需要关注返回的是哪个实现类对象,这种变成方式叫做面向接口编程

迭代器的使用步骤:
1.创建集合对象,往集合中添加元素
2.使用集合中的方法iterator获取迭代器的实现类对象,使用Iterator接口接收(多态)

3.使用iterator中的方法hasNext和next方法进行迭代,取出集合中的元素

public static void main(String[] args) {
        //1.创建集合对象,往集合中添加元素
        //Collection<String> coll = new ArrayList<String>();
        Collection<String> coll = new HashSet<String>();
        coll.add("姚明");
        coll.add("乔丹");
        coll.add("詹姆斯");
        coll.add("科比");
        coll.add("艾弗森");
        //2.使用集合中的方法iterator获取迭代器的实现类对象,使用Iterator接口接收(多态)
        //集合中的数据类型是什么,迭代器的数据类型就是什么,跟着集合走
        Iterator<String> it = coll.iterator();
        //3.使用iterator中的方法hasNext和next方法进行迭代,取出集合中的元素
        //boolean hasNext() 如果仍有元素可以迭代,则返回 true。
        /*boolean b = it.hasNext();
        System.out.println(b);
        //E(String) next() 返回迭代的下一个元素。
        String s = it.next();
        System.out.println(s);
        
        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);
        
        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);
        
        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);
        
        b = it.hasNext();
        System.out.println(b);
        s = it.next();
        System.out.println(s);
        
        b = it.hasNext();
        System.out.println(b);//false,没有元素了
        s = it.next();//没有元素了,在取就报NoSuchElementException没有元素异常
        System.out.println(s);*/
        
        /*
         * 发现以上迭代的过程是一个重复的过程,可以使用循环优化
         * 我们不知道集合中有多少元素,所以可以使用while循环
         * while循环的结束条件:hasNext();返回false
         */
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
        System.out.println("-------------------");
        /*
         * for循环方式迭代器,使用不多
         */
        /*for(Iterator<String> it2 = coll.iterator();it2.hasNext();){
            String s = it2.next();//取出元素,移动指针到下一位
            System.out.println(s);
        }*/
    }

并发修改异常
在迭代的过程中,对集合的长度进行了修改,就会发生并发修改异常
遍历的过程中,集合的长度进行了修改,但是迭代器并不知道,就会产生ConcurrentModificationException

解决方法:
1.迭代就是迭代,不要对集合进行修改
2.使用迭代器Iterator的子接口ListIterator中的方法add/remove,让迭代器自己增加往集合中增加元素/移除元素
这样迭代器本身知道了集合的变化,就不会产生并发修改异常了

void add(E e) 将指定的元素插入列表(可选操作)。
void remove() 从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。

public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        
        list.add(null);
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        
        /*
         * 使用迭代器遍历集合
         */
        //获取迭代器
        Iterator<String> it = list.iterator();
        //使用while遍历集合
        while(it.hasNext()){
            String s = it.next();
            
            /*
             * 判断集合中有没有"abc3"这个元素
             * 如果有,增加一个元素"itcast"
             * 编程技巧:使用equals判断的时候,要把已知的变量写在前边,未知的写在后边,防止空指针异常
             */
            //if(s.equals("abc3")){
            if("abc3".equals(s)){
                //1.迭代就是迭代,不要对集合进行修改
                //list.add("itcast");
            }
            
            System.out.println(s);
        }
        
        System.out.println("------------------");
        
        /*
         * 2.使用迭代器Iterator的子接口ListIterator中的方法add/remove,让迭代器自己增加往集合中增加元素/移除元素
         */
        ListIterator<String> listIt = list.listIterator();
        while(listIt.hasNext()){
            String s = listIt.next();
            if("abc3".equals(s)){
                listIt.add("itcast");
            }
            System.out.println(s);
        }
        System.out.println(list);
    }

增强for
内部是一个迭代器,简化了迭代的代码,使遍历更加简单

Collection接口继承Iterable,所以Collection接口的所有实现类都可以是用增强for

注意:增强for是JDK1.5之后出现的

格式:
for(数据类型(集合/数组的数据类型) 变量名 : 集合名/数组名){
  syso(变量名);
}

Java中的泛型
就是数据类型,在创建对象的时候确定

Java中的泛型是一个伪泛型:在编译的时候有(写代码.java中),运行的时候(.class)没有
随机数:伪随机数

泛型的好处:
1.避免强转,可以直接使用元素特有的方法
2.把运行期的异常,转换编译期异常(编译失败)

定义含有泛型的类
模仿ArrayList集合
public class ArrayList<E>{}
E:是一个未知的数据类型,可能是Integer,可能是String,可能Person
创建类对象的时候确定数据类型

定义格式:
修饰符 class 类名<E>{

}

public class GenericClass<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
    
    public void method(E e){
        System.out.println(e);
    }

定义含有泛型的接口
格式:
修饰符 interface 接口名<泛型>{
  抽象方法(参数<泛型>);

}

  public interface GenericInterface<E> {
     public abstract void method(E e);
 }

/*
 * 1.定义接口的实现类,不管泛型,接口泛型是怎么写的,实现类也怎么写
 *  public class ArrayList<E> implements List<E>{}
 *  创建实现类对象的时候确定泛型的数据类型
 */
class GenericInterfaceImpl1<E> implements GenericInterface<E>{

    @Override
    public void method(E e) {
        System.out.println(e);
    }
}

含有泛型的方法
不是类上定义的泛型,是方法自己定义的泛型
定义格式:在修饰符和返回值类型之间要定义泛型,才能使用
修饰符 <泛型> 返回值类型 方法名(参数<泛型>){
}
方法上的泛型,在调用方法的时候确定数据类型,传递的是什么类型的数据,泛型就是什么类型(和类上的泛型没有关系)
public class GenericMethod<E> {

    /*
     * 定义方法,使用类上的泛型
     */
    public void method(E e){
        System.out.println(e);
    }
    
    /*
     * 定义一个含有泛型的方法
     */
    public <T> void function(T t){
        System.out.println(t);
    }

泛型的通配符:?,代表任意的数据类型

上限限定:? extends E代表只要是E类型的子类即可
下限限定:? super E代表只要是E类型的父类即可

ArrayList集合的构造方法
ArrayList(Collection<? extends E> c)
参数是一个集合,集合的数据类型有要求,只能是ArrayList泛型的子类或者是本身

ArrayList(Collection<? extends E> c)
参数是一个集合,集合的数据类型有要求,只能是ArrayList泛型的子类或者是本身

/*
 * 斗地主案例:
 * 1.准备牌
 * 2.洗牌
 * 3.发牌
 * 4.看牌
 */
public class DouDiZhu {
    public static void main(String[] args) {
        //1.准备牌
        //创建存储54张牌的集合
        ArrayList<String> poker = new ArrayList<String>();
        //存储大王小王
        poker.add("大王");
        poker.add("小王");
        //存储52张牌
        //创建序号的数组
        String[] numbers = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
        //创建花色数组
        String[] colors = {"?","?","?","?"};
        //嵌套遍历两个数组
        for (String number : numbers) {
            for (String color : colors) {
                //System.out.println(color+number);
                //把组合的牌放入到集合中
                poker.add(color+number);
            }
        }
        //System.out.println(poker);
        
        /*
         * 2.洗牌
         * 使用Collections中的方法
         * static void shuffle(List<?> list)  
         */
        Collections.shuffle(poker);
        //System.out.println(poker);
        
        /*
         * 3.发牌
         * 创建4个集合
         * 遍历poker集合
         * 使用poker集合的索引%3发牌
         */
        ArrayList<String> player01 = new ArrayList<String>();
        ArrayList<String> player02 = new ArrayList<String>();
        ArrayList<String> player03 = new ArrayList<String>();
        ArrayList<String> diPai = new ArrayList<String>();
        //遍历poker集合
        for (int i = 0; i < poker.size(); i++) {
            //获取牌
            String s = poker.get(i);
            //先判断索引是否为底牌的索引 51 52 53
            if(i >=51){
                //给底牌发牌
                diPai.add(s);
            }else if(i%3==0){
                //给玩家1发牌
                player01.add(s);
            }else if(i%3==1){
                //给玩家1发牌
                player02.add(s);
            }else if(i%3==2){
                //给玩家1发牌
                player03.add(s);
            }
        }
        //4.看牌
        System.out.println("刘德华:"+player01);
        System.out.println("周润发:"+player02);
        System.out.println("周星驰:"+player03);
        System.out.println("底牌:"+diPai);
    }
}




























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值