【集合】泛型,泛型的好处,泛型通配符,泛型类,泛型方法,泛型接口,增强for循环,静态方法导入,可变参数概述,集合的嵌套遍历,

一.泛型

1.泛型的引入

ClassCastException: 类型转换异常
我们按照正常的写法,在集合中添加一些不同的数据类型的数据,在遍历的时候进行向下转型的时候,发生了错误。

为什么呢?
因为我们在存储数据的时候,不光存储了字符串类型的数据,还存储了Integer类型,Double类型,Student类型的数据。
但是呢,我们在遍历的时候,将获取到的元素都转换成字符串类型,但是,数据的类型不一致导致发生异常。
如果说在我们存储数据的时候,告诉我们只能存储字符串类型的数据,将来再做强转的时候,就不会报错了。
想一想,我们之前学过的数组,在定义的时候,就限定了一个数组只能存放同一种数据类型的数据。
String[] arr = new String[3];
arr[0] = “0”; // arr[1] = new Student();
如果java中的集合模仿着数据,也搞出这样限定数据类型的做法,在创建集合的时候就明确存放一类数据类型就好了。
这样的话,在后面向下转型的时候,就不会发生异常了。
这样的技术,java提供了一个东西叫做:泛型。

2.泛型:把明确数据类型的工作,提前到了编译时期,在创建集合的时候明确存储元素的数据类型。这样的做法有点向把数据类型当作参数一样传递,所以泛型还有一个叫法:参数化类型

**泛型的语句定义格式:
<引用数据类型>
注意:尖括号中的数据类型只能是引用数

3. 泛型的好处:

1、将我们运行时期出现的问题,提前到编译时期
2、不需要做强制类型转换
3、优化了代码。消除了不必要的黄色警告线,使代码看起来更简洁

通过观察API发现,泛型可以出现在类,接口,方法上面,我们看到的类似于这样的都叫泛型,一般来说,泛型出现大多使用的集合中。

 public class GenericDemo {
    public static void main(String[] args) {
        //创建一个List集合对象
//在JDK1.7之后,泛型会进行自动类型推断,因此后面的<>的String就可
//以省略
        ArrayList<String> strings = new ArrayList<>();
        strings.add("java");
    strings.add("hive");
    strings.add("mysql");
    strings.add("web");
 //strings.add(20);//此时只能添加字符串类型,添加其他类型就会
 //报错。

    Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();//此时这里就不
      //需要进行强转,因为现在本身就是一个String类型
      //String s = (String) next; //ClassCastException
            System.out.println(next+"---------
            "+next.length());

            /*结果:
            java---------4
            hive---------4
            mysql---------5
            web---------3
             */
        }
    }
}

4. 泛型通配符

(1)<?> 任意类型,如果没有明确,那么就是Object以及任意的Java类了
(2) ? extends E:向下限定,E及其子类
(3) ? super E :向上限定,E及其父类
public class GenericDemo1 {
    public static void main(String[] args) {
        ArrayList<Animal> list=new ArrayList<>();
        ArrayList<Dog> list1=new ArrayList<>();
        ArrayList<Object> objects = new ArrayList<>();
       ArrayList<Object>list2= new ArrayList<>();


        //1.泛型通配符<?>
   //任意类型,如果没有明确,那么就是Object以及任意的Java类了
        ArrayList<?> list3=new ArrayList<Object>();
        ArrayList<?> list4=new ArrayList<Animal>();
        ArrayList<?> list5=new ArrayList<Dog>();
        ArrayList<?> list6=new ArrayList<Cat>();


     //   2. ? extends 向下限定,E及其子类
 ArrayList<? extends Animal> list9=new ArrayList<Animal>();
 ArrayList<? extends Animal> list7=new ArrayList<Dog>();
 ArrayList<? extends Animal> list8=new ArrayList<Cat>();
 //  ArrayList<? extends Animal> list10=new ArrayList<Object>();
 //Object不可以

        //3. ? super E向上限定,E及其父类
ArrayList<? super Animal>list10=new ArrayList<Object>(); 
ArrayList<? super Animal>list11=new ArrayList<Animal>();
 // ArrayList<? super Animal>list12=new ArrayList<Dog>();
 //Dog类型就不可以


    }
}
class Animal{

}
class Dog extends Animal{}
class Cat extends Animal{}

5.泛型类

把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型

这里的<>里面的内容仅仅表示的使一种参数数据类型,参数类型是一种变量
既然是一种变量,就要符合变量的命名规则,可以使任意符合标识符起名字规则的名字。 一般情况下,在定义的时候,习惯用一个大写字母表示。

泛型类:
publlic class GenericTool1<T>{
private T obj;
public T GetObj(){
return obj;
}
public void SetObj(T obj){
this.obj=obj;

}
}


public class GenericTest1 {
    public static void main(String[] args) {
    //不加泛型默认为Object类型
       /* GenericTool1<Object> objectGenericTool1 = new GenericTool1<>();
        objectGenericTool1.setObj("sf");
        objectGenericTool1.setObj(20);
        objectGenericTool1.setObj(30.05);
        objectGenericTool1.setObj("helloworld");

        System.out.println(objectGenericTool1.getObj());
        
*/
     GenericTool1<String> st1 = new GenericTool1<>();
        st1.setObj("HellowWorld");
        st1.setObj("20");
        System.out.println(st1.getObj());
    }
}

6. 泛型方法

把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)

            public class GenericTool{
            public<T>void show(T t){
            system,out,println(t);}
            }
public class GenericTest2 {
    public static void main(String[] args) {
        GenericTool2 genericTool2 = new GenericTool2();
        genericTool2.show("HelloWorld");
        genericTool2.show(20);
        genericTool2.show(20.36);
        genericTool2.show("大数据");
    }
}

结果:

7.泛型接口

interface GenericTool3 <T>{
    public abstract void show(T t);
}
class GenericTool3Imp <T> implements GenericTool3<T>{

    @Override
    public void show(T t) {
        System.out.println(t);
    }
}


package com.shujia.wyh.day02.day19;

public class GenericTest3 {
    public static void main(String[] args) {
  GenericTool3Imp<Object> obj = new GenericTool3Imp<>();
        obj.show("java");
        obj.show(20);
        obj.show(20.3);
        obj.show("hello");
    }
    }

结果:
在这里插入图片描述

二.增强for循环

JDK1.5之后出现的新特性:
到目前为止,学过哪些知识使JDK1.5之后出现的?
泛型,增强for,包装类,Scanner,枚举

增强for循环概述:简化数组和Collection集合的遍历

语句定义格式:
for(元素数据类型 变量名(自定义) : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
好处:简化遍历

public class ForDemo4 {
    public static void main(String[] args) {
        //1.用增强for循环遍历数组
        System.out.println("=============用增强for循环遍历数组====================");
        int[] arr=new int[]{3,23,65,54,87,10,12};
        for (int a:arr){
            System.out.print(a+",");
        }
        System.out.println();
        System.out.println("==========用增强for循环遍历集合=========================");
        //2.用增强for循环遍历集合
        ArrayList<String> list = new ArrayList<>();
        list.add("java");
        list.add("hive");
        list.add("hadoop");
        list.add("mysql");
        list.add("20");
        list.add("20.13");
//list=null;//如果集合是一个null就会产生空指针异常,因此我们在遍历集合前就要判断集合是否为空
       /* for (Object o:list){
            System.out.println(o);
        }
*/
if(list!=null){
    for (String o:list){
        System.out.println(o);
    }
}
else {
    System.out.println("该集合为空");
}



   //其实增强for循环就是用来替代迭代器的
   //怎么去验证它就是用来替代迭代器的呢?
  //使用并发修改异常去验证,如果你想利用此方法添加元素就不能用增
  //强for循环去遍历,就要用listIterator去遍历
      /*  for (Object o:list){
            if ("java".equals(o)){
                list.add("spark");
    //ConcurrentModificationException就会产生并发修改异常
            }
        }*/
 System.out.println("==========用增强for循环遍历集合=========================");
        //2.用增强for循环遍历集合
    ListIterator<String> iterator = list.listIterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            String s=(String) next;
            if ("hive".equals(s)) {
            iterator.add("spark" );
                System.out.println(s);//hive
            }
        }
        System.out.println(list);
     //[java, hive, spark, hadoop, mysql, 20, 20.13]

}}

结果:

三.静态方法导入

静态导入:
语句定义格式:import static 包名…类名.方法名;
可以直接导入到方法级别

注意事项:方法必须是静态的

package com.shujia.wyh.day02.day19;

public class StaticDemo6 {
    public static void show(){
        System.out.println("欢迎来到合肥");
    }
    public static void show1(String s){
        System.out.println(s);
    }
}


import static java.lang.Math.abs;
import static java.lang.Math.pow;
import static com.shujia.wyh.day02.day19.StaticDemo6.show;
import static com.shujia.wyh.day02.day19.StaticDemo6.show1;
//上面是把StaticDemo6的两个静态show方法,静态导入此类中
//方法静态导入后就不用用类名去调用方法了,就可以直接用该方法
public class StaticImportDemo5 {
    public static void main(String[] args) {
        System.out.println(abs(-100));//100
        System.out.println(pow(2,3));//8.0

        show();//欢迎来到合肥
        show1("你好");//你好

    }
}

结果:

四. 可变参数概述

可变参数概述
定义方法的时候不知道该定义多少个参数
格式
修饰符 返回值类型 方法名(数据类型… 变量名){}
注意:
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

Arrays工具类中的一个方法
public static List asList(T… a)

public class ArgsDemo7 {
    public static void main(String[] args) {
        //1.
    int a=10;
    int b=89;
       sum(a,b);//和为99
       int c=1000;
       sum(a,b,c);//和为1099
       int d=-1990;
       sum(a,b,c,d);//和为-891

//2.
       sum1("学霸",96,63,99,100,20,45,50);
       //学霸学生的成绩为:473


    }
    //1.使用可变参数的形式定义加法的方法
//注意可变参数的变量最终是一个数组的变量名
//这里将来传入多个参数的时候,内部会自动将这多个参数形成一个数组,
//数组名就是我们定义的ints
    public static void sum(int...ints){
        int sum=0;
        for (int num:ints){

            sum+=num;

        }
        System.out.println("和为"+sum);
    }


    //2.当使用可变参数定义方法时候,有其他数据类型参与的时候,将
    //可变参数的定义放在最后

    public static void sum1(String name,int...ints){
         int sum=0;
        for (int num1:ints){
          sum+=num1;
        }
        System.out.println(name+"学生的成绩为:"+sum);
    }
}

结果:

五. 集合的嵌套遍历

需求:目前,数加学院有十五期,十六期。每一期有很多学生,每个学生都是一个学生对象

分析:可以用一个集合表示一个班的学生
十五期的学生:ArrayList classList15;
十六期的学生:ArrayList classList16;
无论是十五也好还是十六期,都是属于数加学院的班级
数加学院本身也可以通过集合表示:ArrayList<ArrayList> shujia; 这样的现象叫做集合嵌套

public class ListQianTaoTest8 {
    public static void main(String[] args) {
        ArrayList<Student9> class15 = new ArrayList<>();
        ArrayList<Student9> class16 = new ArrayList<>();
        ArrayList< ArrayList<Student9>> shujia=new ArrayList<>();
        shujia.add(class15);
        shujia.add(class16);
        //创建15期对象
        Student9 s1=new Student9("小明",20);
        Student9 s2=new Student9("大明",21);
        Student9 s3=new Student9("学神",18);
        //创建16期对象
        Student9 s11=new Student9("大学",13);
        Student9 s12=new Student9("斗皇",23);
        Student9 s13=new Student9("东海",19);

        //添加对象
        class15.add(s1);
        class15.add(s2);
        class15.add(s3);
        class16.add(s11);
        class16.add(s12);
        class16.add(s13);


        //遍历集合
        //利用增强for循环就没法分清哪个师15期的那个是16期,因此我们应该用普通for循环
       /* for (ArrayList<Student9> s:shujia){
            for (Student9 student9:s){
                System.out.println(student9);
            }
        }

        */
//shujia.get(i)表示获取到每个班级再.size()就获取到每个班级的学生数,
        //获到每个班级后再.get(j)就获得每个班级里的学生,i=0是十五期,i=1是十六期班级

        for (int i=0;i<shujia.size();i++){
            if (i==0){
                System.out.println("===============十五期学生=================");
            for (int j=0;j<shujia.get(i).size();j++){
                Student9 student9 = shujia.get(i).get(j);
                System.out.println(student9);

            }

        }
            else if (i==1){
                System.out.println("================十六期学生=================");
                for (int j=0;j<shujia.get(i).size();j++){
                    Student9 student9 = shujia.get(i).get(j);

                    System.out.println(student9);
                }

            }
        }
        System.out.println("==================================");

        //用迭代器去遍历
        Iterator<ArrayList<Student9>> iterator = shujia.iterator();
        while (iterator.hasNext()){
            ArrayList<Student9> next = iterator.next();
            ArrayList<Student9> student9s=(ArrayList<Student9>) next;
            Iterator<Student9> iterator1 = student9s.iterator();
            while (iterator1.hasNext()){
                Student9 next1 = iterator1.next();
                Student9 student9=(Student9) next1;
                System.out.println(student9);
            }
        }


    }
}

结果:

例题

获取10个1-20之间的随机数,要求不能重复
1、由于我们不确定获取随机数的次数,长度不好确定,所以我们选择集合
2、随机数生成的方式:Random类:nextInt(int num): 左闭右开

public class RandomTest10 {
    public static void main(String[] args) {
        //1、创建随机数对象
        Random random = new Random();
        //2、创建集合对象存储随机数
        ArrayList<Integer> list= new ArrayList<>();
        //定义一个变量统计集合中是否有10个元素
        int count=0;
        while (count<10){
            //生成随机数
            int num = random.nextInt(20) + 1;
            //判断集合中是否包含这个随机数
            if (!list.contains(num)){
                list.add(num);
                count++;
            }
        }
        System.out.println(list);

    }
}

结果:

例题:

键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值
分析:

1、由于不知道输入多少次,所以用while循环进行输入
2、用集合存储数据
3、toArray()
4、Arrays.sort()
5、取最后一个元素就是最大值

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class ListTest11 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Scanner sc=new Scanner(System.in);
        boolean flag=true;

        while (flag){
            int num=sc.nextInt();
            if (num==0){
                flag=false;
                System.out.println("录入数据完毕");
            }
            else {
                list.add(num);
            }

            }
        //将集合转换成数组
        Object[] objects = list.toArray();
        Arrays.sort(objects);
        System.out.println("集合中的最大数
        为:"+objects[objects.length-1]);


    }

结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值