zoukankan      html  css  js  c++  java
  • 集合之 collection 迭代器 泛型 (任意类型)

    主要内容

    - Collection集合
    - 迭代器
    - 增强for
    - 泛型

    # 第一章 Collection集合

    1.1 集合概述

    * **集合**:集合是java中提供的一种容器,可以用来存储多个数据。

    集合和数组的区别

    * 数组的长度是固定的。集合的长度是可变的。
    * 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。

    ## 1.2 集合框架

    集合按照其存储结构可以分为两大类,Collection`集合,Map集合。

    * **Collection**:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。

    `List`的特点有序、可重复。`Set`的特点是无序,不可重复。

    `List`:ArrayLst 和 LinkList

     

    ## 1.3 Collection 常用功能

    Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:

    * `public boolean add(E e)`: 把给定的对象添加到当前集合中 。
    * `public void clear()` :清空集合中所有的元素。
    * `public boolean remove(E e)`: 把给定的对象在当前集合中删除。
    * `public boolean contains(E e)`: 判断当前集合中是否包含给定的对象。
    * `public boolean isEmpty()`: 判断当前集合是否为空。
    * `public int size()`: 返回集合中元素的个数。
    * `public Object[] toArray()`: 把集合中的元素,存储到数组中。

    方法演示:

    package com.itheima.demo01.Collection;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashSet;
    
    /*
        java.util.Collection接口
            所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法
            任意的单列集合都可以使用Collection接口中的方法
    
    
        共性的方法:
          public boolean add(E e):  把给定的对象添加到当前集合中 。
          public void clear() :清空集合中所有的元素。
          public boolean remove(E e): 把给定的对象在当前集合中删除。
          public boolean contains(E e): 判断当前集合中是否包含给定的对象。
          public boolean isEmpty(): 判断当前集合是否为空。
          public int size(): 返回集合中元素的个数。
          public Object[] toArray(): 把集合中的元素,存储到数组中。
     */
    public class Demo01Collection {
        public static void main(String[] args) {
            //创建集合对象,可以使用多态
            //Collection<String> coll = new ArrayList<>();
            Collection<String> coll = new HashSet<>();
            System.out.println(coll);//重写了toString方法  []
    
            /*
                public boolean add(E e):  把给定的对象添加到当前集合中 。
                返回值是一个boolean值,一般都返回true,所以可以不用接收
             */
            boolean b1 = coll.add("张三");
            System.out.println("b1:"+b1);//b1:true
            System.out.println(coll);//[张三]
            coll.add("李四");
            coll.add("李四");
            coll.add("赵六");
            coll.add("田七");
            System.out.println(coll);//[张三, 李四, 赵六, 田七]
    
            /*
                public boolean remove(E e): 把给定的对象在当前集合中删除。
                返回值是一个boolean值,集合中存在元素,删除元素,返回true
                                    集合中不存在元素,删除失败,返回false
             */
            boolean b2 = coll.remove("赵六");
            System.out.println("b2:"+b2);//b2:true
    
            boolean b3 = coll.remove("赵四");
            System.out.println("b3:"+b3);//b3:false
            System.out.println(coll);//[张三, 李四, 田七]
    
            /*
                public boolean contains(E e): 判断当前集合中是否包含给定的对象。
                包含返回true
                不包含返回false
             */
            boolean b4 = coll.contains("李四");
            System.out.println("b4:"+b4);//b4:true
    
            boolean b5 = coll.contains("赵四");
            System.out.println("b5:"+b5);//b5:false
    
            //public boolean isEmpty(): 判断当前集合是否为空。 集合为空返回true,集合不为空返回false
            boolean b6 = coll.isEmpty();
            System.out.println("b6:"+b6);//b6:false
    
            //public int size(): 返回集合中元素的个数。
            int size = coll.size();
            System.out.println("size:"+size);//size:3
    
            //public Object[] toArray(): 把集合中的元素,存储到数组中。
            Object[] arr = coll.toArray();
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
    
            //public void clear() :清空集合中所有的元素。但是不删除集合,集合还存在
            coll.clear();
            System.out.println(coll);//[]
            System.out.println(coll.isEmpty());//true
        }
    }

     

    ## 第二章 Iterator迭代器

    ## 2.1 Iterator接口

    `Iterator`与`Collection`、`Map`接口有所不同,`Collection`接口与`Map`接口主要用于存储元素,而`Iterator`主要用于迭代访问(即遍历)`Collection`中的元素,因此`Iterator`对象也被称为迭代器。

    想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:

    * `public Iterator iterator()`: 获取集合对应的迭代器,用来遍历集合中的元素的。

    Iterator接口的常用方法如下:

     E next()`:返回迭代的下一个元素。
     hasNext()`:如果仍有元素可以迭代,则返回 true。

        public static void main(String[] args) {
            //创建一个集合对象
            Collection<String> coll = new ArrayList<>();
            //往集合中添加元素
            coll.add("姚明");
            coll.add("科比");
            coll.add("麦迪");
            coll.add("詹姆斯");
            coll.add("艾弗森");
    
            /*
                1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
                注意:
                    Iterator<E>接口也是有泛型的,迭代器的泛型跟着集合走,集合是什么泛型,迭代器就是什么泛型
             */
            //多态  接口            实现类对象
            Iterator<String> it = coll.iterator();
    
            while(it.hasNext()){
                String e = it.next();
                System.out.println(e);
            }
            System.out.println("----------------------");
            for(Iterator<String> it2 = coll.iterator();it2.hasNext();){
                String e = it2.next();
                System.out.println(e);
            }

    ## 2.3 增强for

    增强for循环(也称for each循环)是**JDK1.5**以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

    public class Demo02Foreach {
        public static void main(String[] args) {
            demo02();
            demo01();
        }
    
        //使用增强for循环遍历集合
        private static void demo02() {
            ArrayList<String> list = new ArrayList<>();
            list.add("aaa");
            list.add("bbb");
            list.add("ccc");
            list.add("ddd");
            for(String s : list){
                System.out.println(s);
            }
        }
    
        //使用增强for循环遍历数组
        private static void demo01() {
            int[] arr = {1,2,3,4,5};
            for(int i:arr){
                System.out.println(i);
            }
        }
    }

     

    # 第三章 泛型

    ## 3.1 泛型概述

    在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。

    大家观察下面代码:

    package 泛型;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Demo01Generic {
        public static void main(String[] args) {
            show02();show01();
        }
    
        /*
            创建集合对象,使用泛型
            好处:
                1.避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
                2.把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)
             弊端:
                泛型是什么类型,只能存储什么类型的数据
         */
        private static void show02() {
            ArrayList<String> list = new ArrayList<>();
            list.add("abc");
            //list.add(1);//add(java.lang.String)in ArrayList cannot be applied to (int)
    
            //使用迭代器遍历list集合
            Iterator<String> it = list.iterator();
            while(it.hasNext()){
                String s = it.next();
                System.out.println(s+"->"+s.length());
            }
        }
    
        /*
            创建集合对象,不使用泛型
            好处:
                集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据
            弊端:
                不安全,会引发异常
         */
        private static void show01() {
            ArrayList list = new ArrayList();
            list.add("abc");
            list.add(1);
    
            //使用迭代器遍历list集合
            //获取迭代器
            Iterator it = list.iterator();
            //使用迭代器中的方法hasNext和next遍历集合
            while(it.hasNext()){
                //取出元素也是Object类型
                Object obj = it.next();
                System.out.println(obj);
    
                //想要使用String类特有的方法,length获取字符串的长度;不能使用  多态 Object obj = "abc";
                //需要向下转型
                //会抛出ClassCastException类型转换异常,不能把Integer类型转换为String类型
                String s = (String)obj;
                System.out.println(s.length());
            }
        }
    }

     

    ## 3.2 使用泛型的好处

    上一节只是讲解了泛型的引入,那么泛型带来了哪些好处呢?

    * 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
    * 避免了类型强转的麻烦。

    通过我们如下代码体验一下:

    public class Demo02GenericClass {
        public static void main(String[] args) {
            //不写泛型默认为Object类型
            GenericClass gc = new GenericClass();
            gc.setName("只能是字符串");
            Object obj = gc.getName();
    
            //创建GenericClass对象,泛型使用Integer类型
            GenericClass<Integer> gc2 = new GenericClass<>();
            gc2.setName(1);
    
            Integer name = gc2.getName();
            System.out.println(name);
    
            //创建GenericClass对象,泛型使用String类型
            GenericClass<String> gc3 = new GenericClass<>();
            gc3.setName("小明");
            String name1 = gc3.getName();
            System.out.println(name1);
        }
    }
    package 泛型;
    /*
        测试含有泛型的方法
     */
    public class Demo03GenericMethod {
        public static void main(String[] args) {
            //创建GenericMethod对象
            GenericMethod gm = new GenericMethod();
    
            /*
                调用含有泛型的方法method01
                传递什么类型,泛型就是什么类型
             */
            gm.method01(10);
            gm.method01("abc");
            gm.method01(8.8);
            gm.method01(true);
    
            gm.method02("静态方法,不建议创建对象使用");
    
            //静态方法,通过类名.方法名(参数)可以直接使用
            GenericMethod.method02("静态方法");
            GenericMethod.method02(1);
        }
    }
    package 泛型;
    /*
        测试含有泛型的接口
     */
    public class Demo04GenericInterface {
        public static void main(String[] args) {
            //创建GenericInterfaceImpl1对象
            GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
            gi1.method("字符串");
    
            //创建GenericInterfaceImpl2对象
            GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
            gi2.method(10);
    
            GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();
            gi3.method(8.8);
           
        }
    }

    ?表示类型

    package 泛型;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    /*
        泛型的通配符:
            ?:代表任意的数据类型
        使用方式:
            不能创建对象使用
            只能作为方法的参数使用
     */
    public class Demo05Generic {
        public static void main(String[] args) {
            ArrayList<Integer> list01 = new ArrayList<>();
            list01.add(1);
            list01.add(2);
    
            ArrayList<String> list02 = new ArrayList<>();
            list02.add("a");
            list02.add("b");
    
            printArray(list01);
            printArray(list02);
    
            //ArrayList<?> list03 = new ArrayList<?>();
        }
    
        /*
            定义一个方法,能遍历所有类型的ArrayList集合
            这时候我们不知道ArrayList集合使用什么数据类型,可以泛型的通配符?来接收数据类型
            注意:
                泛型没有继承概念的
         */
        public static void printArray(ArrayList<?> list){
            //使用迭代器遍历集合
            Iterator<?> it = list.iterator();
            while(it.hasNext()){
                //it.next()方法,取出的元素是Object,可以接收任意的数据类型
                Object o = it.next();
                System.out.println(o);
            }
        }
    }

    ### 通配符高级使用----受限泛型

    之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的**上限**和**下限**。

    **泛型的上限**:

    * **格式**: `类型名称 <? extends 类 > 对象名称`
    * **意义**: `只能接收该类型及其子类`

    **泛型的下限**:

    - **格式**: `类型名称 <? super 类 > 对象名称`
    - **意义**: `只能接收该类型及其父类型`

    比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类

    package 泛型;
    
    import java.util.ArrayList;
    import java.util.Collection;
    
    /*
        泛型的上限限定: ? extends E  代表使用的泛型只能是E类型的子类/本身
        泛型的下限限定: ? super E    代表使用的泛型只能是E类型的父类/本身
     */
    public class Demo06Generic {
        public static void main(String[] args) {
            Collection<Integer> list1 = new ArrayList<Integer>();
            Collection<String> list2 = new ArrayList<String>();
            Collection<Number> list3 = new ArrayList<Number>();
            Collection<Object> list4 = new ArrayList<Object>();
    
            getElement1(list1);
            //getElement1(list2);//报错
            getElement1(list3);
            //getElement1(list4);//报错
    
            //getElement2(list1);//报错
            //getElement2(list2);//报错
            getElement2(list3);
            getElement2(list4);
    
            /*
                类与类之间的继承关系
                Integer extends Number extends Object
                String extends Object
             */
    
        }
        // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
        public static void getElement1(Collection<? extends Number> coll){}
        // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
        public static void getElement2(Collection<? super Number> coll){}
    }
    public class GenericClass<E> {
        private E name;
    
        public E getName() {
            return name;
        }
    
        public void setName(E name) {
            this.name = name;
        }
    }
    接口
    public interface GenericInterface<I> {
    public abstract void method(I i);
    }


    package 泛型; /* 含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走 就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型 public interface List<E>{ boolean add(E e); E get(int index); } public class ArrayList<E> implements List<E>{ public boolean add(E e) {} public E get(int index) {} } */ public class GenericInterfaceImpl2<I> implements GenericInterface<I> { @Override public void method(I i) { System.out.println(i); } } 方法 package 泛型; /* 定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间 格式: 修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){ 方法体; } 含有泛型的方法,在调用方法的时候确定泛型的数据类型 传递什么类型的参数,泛型就是什么类型 */ public class GenericMethod { //定义一个含有泛型的方法 public <M> void method01(M m){ System.out.println(m); } //定义一个含有泛型的静态方法 public static <S> void method02(S s){ System.out.println(s); } }

    # 第四章 集合综合案例

    ## 4.1 案例介绍

    按照斗地主的规则,完成洗牌发牌的动作。
    具体规则:

    使用54张牌打乱顺序,三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。

    ## 4.2 案例分析

    * 准备牌:

    牌可以设计为一个ArrayList<String>,每个字符串为一张牌。
    每张牌由花色数字两部分组成,我们可以使用花色集合与数字集合嵌套迭代完成每张牌的组装。
    牌由Collections类的shuffle方法进行随机排序。

    * 发牌

    将每个人以及底牌设计为ArrayList<String>,将最后3张牌直接存放于底牌,剩余牌通过对3取模依次发牌。


    * 看牌

    直接打印每个集合。

    ## 4.3 代码实现

    ~~~java
    import java.util.ArrayList;
    import java.util.Collections;

    public class Poker {
    public static void main(String[] args) {
    /*
    * 1: 准备牌操作
    */
    //1.1 创建牌盒 将来存储牌面的
    ArrayList<String> pokerBox = new ArrayList<String>();
    //1.2 创建花色集合
    ArrayList<String> colors = new ArrayList<String>();

    //1.3 创建数字集合
    ArrayList<String> numbers = new ArrayList<String>();

    //1.4 分别给花色 以及 数字集合添加元素
    colors.add("♥");
    colors.add("♦");
    colors.add("♠");
    colors.add("♣");

    for(int i = 2;i<=10;i++){
    numbers.add(i+"");
    }
    numbers.add("J");
    numbers.add("Q");
    numbers.add("K");
    numbers.add("A");
    //1.5 创造牌 拼接牌操作
    // 拿出每一个花色 然后跟每一个数字 进行结合 存储到牌盒中
    for (String color : colors) {
    //color每一个花色
    //遍历数字集合
    for(String number : numbers){
    //结合
    String card = color+number;
    //存储到牌盒中
    pokerBox.add(card);
    }
    }
    //1.6大王小王
    pokerBox.add("小☺");
    pokerBox.add("大☠");
    // System.out.println(pokerBox);
    //洗牌 是不是就是将 牌盒中 牌的索引打乱
    // Collections类 工具类 都是 静态方法
    // shuffer方法
    /*
    * static void shuffle(List<?> list)
    * 使用默认随机源对指定列表进行置换。
    */
    //2:洗牌
    Collections.shuffle(pokerBox);
    //3 发牌
    //3.1 创建 三个 玩家集合 创建一个底牌集合
    ArrayList<String> player1 = new ArrayList<String>();
    ArrayList<String> player2 = new ArrayList<String>();
    ArrayList<String> player3 = new ArrayList<String>();
    ArrayList<String> dipai = new ArrayList<String>();

    //遍历 牌盒 必须知道索引
    for(int i = 0;i<pokerBox.size();i++){
    //获取 牌面
    String card = pokerBox.get(i);
    //留出三张底牌 存到 底牌集合中
    if(i>=51){//存到底牌集合中
    dipai.add(card);
    } else {
    //玩家1 %3 ==0
    if(i%3==0){
    player1.add(card);
    }else if(i%3==1){//玩家2
    player2.add(card);
    }else{//玩家3
    player3.add(card);
    }
    }
    }
    //看看
    System.out.println("令狐冲:"+player1);
    System.out.println("田伯光:"+player2);
    System.out.println("绿竹翁:"+player3);
    System.out.println("底牌:"+dipai);
    }
    }
    ~~~

     

  • 相关阅读:
    UVA 1513
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:.geodatabase创建,创建时内容缺失问题总结
    《ArcGIS Runtime SDK for Android开发笔记》——问题集:使用TextSymbol做标注显示乱码
    《ArcGIS Runtime SDK for Android开发笔记》——(7)、示例代码arcgis-runtime-samples-android的使用
    《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析
    《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)
    《ArcGIS Runtime SDK for Android开发笔记》——(4)、基于Android Studio构建ArcGIS Android开发环境
    《ArcGIS Runtime SDK for Android开发笔记》——(3)、ArcGIS Runtime SDK概述
    《ArcGIS Runtime SDK for Android开发笔记》——(2)、Android Studio基本配置与使用
    《ArcGIS Runtime SDK for Android开发笔记》——(1)、Android Studio下载与安装
  • 原文地址:https://www.cnblogs.com/qj696/p/14305246.html
Copyright © 2011-2022 走看看