java基础-常用类、集合、IO流

一、常用类

1、包装类

1.1、基本类型包装类(记忆)
  • 基本类型包装类的作用

    • 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据

    • 常用的操作之一:用于基本数据类型与字符串之间的转换

  • 基本类型对应的包装类

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

1.2、Integer类(应用)

  • Integer类概述

    包装一个对象中的原始类型 int 的值

  • Integer类构造方法

    方法名说明
    public Integer(int value)根据 int 值创建 Integer 对象(过时)
    public Integer(String s)根据 String 值创建 Integer 对象(过时)
    public static Integer valueOf(int i)返回表示指定的 int 值的 Integer 实例
    public static Integer valueOf(String s)返回一个保存指定值的 Integer 对象 String
  • 示例代码

public class IntegerDemo { 
	public static void main(String[] args) { 
        
		//public Integer(int value):根据 int 值创建 Integer 对象(过时) 
        Integer i1 = new Integer(100); 
		System.out.println(i1); 
		//public Integer(String s):根据 String 值创建 Integer 对象(过时) 
        Integer i2 = new Integer("100"); 
        // Integer i2 = new Integer("abc"); //NumberFormatException 
        System.out.println(i2); 
        System.out.println("--------"); 
        //public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 实例 
        Integer i3 = Integer.valueOf(100); 
        System.out.println(i3); 
        //public static Integer valueOf(String s):返回一个保存指定值的Integer对象String 
        Integer i4 = Integer.valueOf("100"); 
        System.out.println(i4); 
    } 
} 

1.3、int和String类型的相互转换(记忆)

  • int转换为String

    • 转换方式

      • 方式一:直接在数字后加一个空字符串
      • 方式二:通过String类静态方法valueOf()
    • 示例代码

      public class IntegerDemo { 
          public static void main(String[] args) { 
              //int --- String 
              int number = 100; 
              //方式1 
              String s1 = number + ""; 
              System.out.println(s1); 
              //方式2 
              //public static String valueOf(int i) 
              String s2 = String.valueOf(number); 
              System.out.println(s2); 
              System.out.println("--------"); 
          } 
      }
      
  • String转换为int

    • 转换方式

      • 方式一:先将字符串数字转成Integer,再调用valueOf()方法

      • 方式二:通过Integer静态方法parseInt()进行转换

    • 示例代码

      public class IntegerDemo { 
          public static void main(String[] args) { 
              //String --- int 
              String s = "100"; 
              //方式1:String --- Integer --- int 
              Integer i = Integer.valueOf(s); 
              //public int intValue() 
              int x = i.intValue(); 
              System.out.println(x); 
              //方式2 
              //public static int parseInt(String s) 
              int y = Integer.parseInt(s); 
              System.out.println(y); 
          }
      }
      

1.4、字符串数据排序案例(应用)

  • 案例需求

    有一个字符串:“91 27 46 38 50”,请写程序实现最终输出结果是:“27 38 46 50 91”

  • 代码实现

    public class IntegerTest { 
        public static void main(String[] args) { 
            //定义一个字符串 
            String s = "91 27 46 38 50"; 
            //把字符串中的数字数据存储到一个int类型的数组中 
            String[] strArray = s.split(" "); 
            // for(int i=0; i<strArray.length; i++) { 
            	// System.out.println(strArray[i]); 
            	// } 
            //定义一个int数组,把 String[] 数组中的每一个元素存储到 int 数组中 
            int[] arr = new int[strArray.length]; 
            for(int i=0; i<arr.length; i++) { 
                arr[i] = Integer.parseInt(strArray[i]); 
            }
            //对 int 数组进行排序 
            Arrays.sort(arr); 
            //把排序后的int数组中的元素进行拼接得到一个字符串,这里拼接采用StringBuilder来实现 
            StringBuilder sb = new StringBuilder(); 
            for(int i=0; i<arr.length; i++) { 
                if(i == arr.length - 1) { 
                    sb.append(arr[i]); 
                } else { 
                    sb.append(arr[i]).append(" "); 
                } 
            }
            String result = sb.toString();
            //输出结果 
            System.out.println(result);
        }
    }
    

1.5、自动拆箱和自动装箱(理解)

  • 自动装箱

    把基本数据类型转换为对应的包装类类型

  • 自动拆箱

    把包装类类型转换为对应的基本数据类型

  • 示例代码

    Integer i = 100; // 自动装箱 
    i += 200; // i = i + 200; i + 200 自动拆箱;i = i + 200; 是自动装箱
    

2、时间日期类

2.1、Date类(应用)

  • Date类概述

    Date 代表了一个特定的时间,精确到毫秒

  • Date类构造方法

    方法名说明
    public Date()分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
    public Date(long date)分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
  • 示例代码

    public class DateDemo01 { 
        public static void main(String[] args) { 
            //public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 
            Date d1 = new Date(); 
            System.out.println(d1); 
            //public Date(long date):分配一个 Date对象,并将其初始化为表示从标准基准时间起 指定的毫秒数
            long date = 1000*60*60; 
            Date d2 = new Date(date); 
            System.out.println(d2); 
        } 
    }
    

2.2、Date类常用方法(应用)

  • 常用方法

    方法名说明
    public long getTime()获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
    public void setTime(long time)设置时间,给的是毫秒值
  • 示例代码

    public class DateDemo02 { 
        public static void main(String[] args) { 
            //创建日期对象 
            Date d = new Date(); 
            //public long getTime():获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 
            // System.out.println(d.getTime()); 
            // System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年"); 
            //public void setTime(long time):设置时间,给的是毫秒值 
            // long time = 1000*60*60; 
            long time = System.currentTimeMillis(); 
            d.setTime(time); 
            System.out.println(d); 
        } 
    }
    

2.3、SimpleDateFormat类(应用)

  • SimpleDateFormat类概述

    SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。

    我们重点学习日期格式化和解析

  • SimpleDateFormat类构造方法

    方法名说明
    public SimpleDateFormat()构造一个SimpleDateFormat,使用默认模式和日期格式
    public SimpleDateFormat(String pattern)构造一个SimpleDateFormat使用给定的模式和默认的日期格式
  • SimpleDateFormat类的常用方法

    • 格式化(从Date到String)

      • public fifinal String format(Date date):将日期格式化成日期/时间字符串
    • 解析(从String到Date)

      • public Date parse(String source):从给定字符串的开始解析文本以生成日期
  • 示例代码

    public class SimpleDateFormatDemo { 
        public static void main(String[] args) throws ParseException {
        //日期转成字符串
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String s = format.format(date);
        System.out.println(s);
        //字符串转换成日期
        String ss = "2022-08-05 11:29:35";
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date s1 = format1.parse(ss);
        System.out.println(s1);
        }
    }
    

2.4、日期工具类案例(应用)

  • 案例需求

    定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析为指定格式 的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法

  • 代码实现

    • 工具类

      public class DateUtils {
      	/* 
      	把日期转为指定格式的字符串 
      	返回值类型:String 
      	参数:Date date, String format 
      	*/
          public static String dateToString(Date date, String format){
              SimpleDateFormat sdf = new SimpleDateFormat(format);
              String s = sdf.format(date);
              return s;
          }
      	/* 
      	把字符串解析为指定格式的日期 
      	返回值类型:Date 
      	参数:String date, String format 
      	*/
          public static Date stringToDate(String date,String format) throws ParseException {
              SimpleDateFormat sdf = new SimpleDateFormat(format);
              Date strDate = sdf.parse(date);
              return strDate;
          }
      }
      
    • 测试类

      public class DateDemo { 
          public static void main(String[] args) throws ParseException { 
              //创建日期对象 
              Date d = new Date(); 
              
              String s1 = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss"); 
              System.out.println(s1); 
              
              String s2 = DateUtils.dateToString(d, "yyyy年MM月dd日"); 
              System.out.println(s2); 
              
              String s3 = DateUtils.dateToString(d, "HH:mm:ss"); 
              System.out.println(s3); 
              System.out.println("--------"); 
              
              String s = "2048-08-09 12:12:12"; 
              Date dd = DateUtils.stringToDate(s, "yyyy-MM-dd HH:mm:ss"); 
              System.out.println(dd); 
          } 
      }
      

2.5、Calendar类(应用)

  • Calendar类概述

    Calendar 为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法

    Calendar 提供了一个类方法 getInstance 用于获取这种类型的一般有用的对象。

    该方法返回一个Calendar 对象。

    其日历字段已使用当前日期和时间初始化:Calendar rightNow = Calendar.getInstance();

  • Calendar类常用方法

    方法名说明
    public int get(int fifield)返回给定日历字段的值
    public abstract void add(int fifield, int amount)根据日历的规则,将指定的时间量添加或减去给定的日历字段
    public fifinal void set(int year,int month,int date)设置当前日历的年月日
  • 示例代码

    public class CalendarDemo { 
        public static void main(String[] args) { 
            //获取日历类对象 
            Calendar c = Calendar.getInstance(); 
            //public int get(int field):返回给定日历字段的值 
            int year = c.get(Calendar.YEAR); 
            int month = c.get(Calendar.MONTH) + 1; 
            int date = c.get(Calendar.DATE); 
            System.out.println(year + "年" + month + "月" + date + "日"); 
            //public abstract void add(int field, int amount):根据日历的规则,将指定的时 间量添加或减去给定的日历字段 
            //需求1:3年前的今天 
            // c.add(Calendar.YEAR,-3); 
            // year = c.get(Calendar.YEAR); 
            // month = c.get(Calendar.MONTH) + 1; 
            // date = c.get(Calendar.DATE); 
            // System.out.println(year + "年" + month + "月" + date + "日"); 
            
            //需求2:10年后的10天前 
            // c.add(Calendar.YEAR,10); 
            // c.add(Calendar.DATE,-10); 
            // year = c.get(Calendar.YEAR); 
            // month = c.get(Calendar.MONTH) + 1; 
            // date = c.get(Calendar.DATE); 
            // System.out.println(year + "年" + month + "月" + date + "日"); 
            
            //public final void set(int year,int month,int date):设置当前日历的年月日 
            c.set(2050,10,10); //表示2050年11月14日
            year = c.get(Calendar.YEAR); 
            month = c.get(Calendar.MONTH) + 1; 
            date = c.get(Calendar.DATE); 
            System.out.println(year + "年" + month + "月" + date + "日"); 
        } 
    }
    

2.6、二月天案例(应用)

  • 案例需求

    获取任意一年的二月有多少天

  • 代码实现

    public class CalendarTest { 
        public static void main(String[] args) {
            //键盘录入任意的年份
            Scanner scan = new Scanner(System.in);
            System.out.print("输入年份:");
            int year = scan.nextInt();
            //设置日历对象的年、月、日
            Calendar c = Calendar.getInstance();
            c.set(year,2,1);//月份数字是2表示是3月份
            //3月1日往前推一天,就是2月的最后一天
            c.add(Calendar.DATE,-1);
            System.out.println(year+"年的二月份有"+c.get(Calendar.DATE)+"天");
        }
    }
    

3、异常

3.1、异常(记忆)

  • 异常的概述

    异常就是程序出现了不正常的情况

  • 异常的体系结构

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xMbhDphm-1660040562540)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659930747730.png)]

    • Error :严重问题,不需要处理
    • Exception:称为异常类,它表示程序本身可以处理的问题
      • RuntimeException:在编译期是不检查的,出现问题后,需要我们回来修改代码
      • 非RuntimeException:编译期就必须处理的,否则程序不能通过编译,就更不能正常运行了

3.2、JVM默认处理异常的方式(理解)

  • 如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:

    • 把异常的名称,错误原因及异常出现的位置等信息输出在了控制台

    • 程序停止执行

3.3、try-catch方式处理异常(应用)

格式:

try {
    可能出现异常的代码; 
} catch(异常类名 变量名) { 
    异常的处理代码; 
}
  • 执行流程

    • 程序从 try 里面的代码开始执行

    • 出现异常,就会跳转到对应的 catch 里面去执行

    • 执行完毕之后,程序还可以继续往下执行

  • 示例代码

    public class ExceptionDemo01 { 
        public static void main(String[] args) { 
            System.out.println("开始"); 
            method(); 
            System.out.println("结束"); 
        }
        
        public static void method() { 
            try {
                int[] arr = {1, 2, 3}; 
                System.out.println(arr[3]); 
                System.out.println("这里能够访问到吗"); 
            } catch (ArrayIndexOutOfBoundsException e) { 
                // System.out.println("你访问的数组索引不存在,请回去修改为正确的索引"); 
                e.printStackTrace(); 
            } 
        } 
    }
    

3.4、Throwable成员方法(应用)

常用方法:

方法名说明
public String getMessage()返回此 throwable 的详细消息字符串
public String toString()返回此可抛出的简短描述
public void printStackTrace()把异常的错误信息输出在控制台

示例代码:

public class ExceptionDemo02 { 
    public static void main(String[] args) { 
        System.out.println("开始"); 
        method(); 
        System.out.println("结束"); 
    }
    
    public static void method() { 
        try {
            int[] arr = {1, 2, 3}; 
            System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException(); 
            System.out.println("这里能够访问到吗"); 
        } catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException(); 
            // e.printStackTrace(); 
            
            //public String getMessage():返回此 throwable 的详细消息字符串 
            // System.out.println(e.getMessage()); 
            //Index 3 out of bounds for length 3 
            
            //public String toString():返回此可抛出的简短描述 
            // System.out.println(e.toString()); 
            //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
            //public void printStackTrace():把异常的错误信息输出在控制台 
            e.printStackTrace(); 
            // java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 
            // at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18) 
            // at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11) 
        } 
    } 
}

3.5、编译时异常和运行时异常的区别(记忆)

  • 编译时异常

    • 都是Exception类及其子类

    • 必须显式处理,否则程序就会发生错误,无法通过编译

  • 运行时异常

    • 都是RuntimeException类及其子类

    • 无需显示处理,也可以和编译时异常一样处理

3.6、throws方式处理异常(应用)

格式:

public void 方法() throws 异常类名 {
}

示例:

/*
    throws 异常类名;
    这个格式是跟在方法的括号后面的
 */
public class ExceptionDemo {
    public static void main(String[] args) {
        System.out.println("开始");
//        method();
        try {
            method2();
        }catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("结束");
    }

    //编译时异常
    public static void method2() throws ParseException {
        String s = "2048-08-09";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date d = sdf.parse(s);
        System.out.println(d);
    }

    //运行时异常
    public static void method() throws ArrayIndexOutOfBoundsException {
        int[] arr = {1, 2, 3};
        System.out.println(arr[3]);
    }
}
  • 注意事项

    • 这个throws格式是跟在方法的括号后面的

    • 编译时异常必须要进行处理,两种处理方案:try…catch …或者 throws,如果采用 throws 这种方案, 将来谁调用谁处理

    • 运行时异常可以不处理,出现问题后,需要我们回来修改代码

3.7、throws和throw的区别(记忆)

  • throws:
    • 用在方法声明后面,跟的是异常类名
    • 表示抛出异常,由该方法的调用者来处理
    • 表示出现异常的一种可能性,并不一定会发生这些异常
  • throw:
    • 用在方法体内,跟的是异常对象名
    • 表示抛出异常,由方法体内的语句处理
    • 执行throw一定抛出了某种异常

3.8、自定义异常(应用)

自定义异常类

public class ScoreException extends Exception {

    public ScoreException() {}

    public ScoreException(String message) {
        super(message);
    }
}

老师类

public class Teacher {

    public void checkScore(int score) throws ScoreException {
        if(score<0 || score>100) {
			//throw new ScoreException();
            throw new ScoreException("你给的分数有误,分数应该在0-100之间");
        } else {
            System.out.println("成绩正常");
        }
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入分数:");
        int score = sc.nextInt();
        Teacher t = new Teacher();
        try {
            t.checkScore(score);
        } catch (ScoreException e) {
            e.printStackTrace();
        }
    }
}

二、集合

1、Collection集合

1.1、集合体系结构【记忆】

  • 集合类的特点

    提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变

  • 集合类的体系图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FxeYgDCW-1660040562542)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659939022023.png)]

1.2、Collection集合概述和基本使用【应用】

  • Collection集合概述

    • 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素

    • JDK 不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现

  • Collection集合基本使用

    /*
        创建Collection集合的对象
            多态的方式
            ArrayList()
     */
    public class CollectionDemo01 {
        public static void main(String[] args) {
            //创建Collection集合的对象
            Collection<String> c = new ArrayList<String>();
    
            //添加元素:boolean add(E e)
            c.add("hello");
            c.add("world");
            c.add("java");
    
            //输出集合对象
            System.out.println(c);
        }
    }
    

1.3、Collection集合的常用方法【应用】

方法名说明
boolean add(E e)添加元素
boolean remove(Object o)从集合中移除指定的元素
void clear()清空集合中的元素
boolean contains(Object o)判断集合中是否存在指定的元素
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中元素的个数

1.4、Collection集合的遍历【应用】

  • 迭代器的介绍

    • 迭代器,集合的专用遍历方式

    • Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到

    • 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的

  • Collection集合的遍历

    /*
        Iterator:迭代器,集合的专用遍历方式
            Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
            迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的
    
        Iterator中的常用方法
            E next():返回迭代中的下一个元素
            boolean hasNext():如果迭代具有更多元素,则返回 true
     */
    public class IteratorDemo01 {
        public static void main(String[] args) {
            //创建集合对象
            Collection<String> c = new ArrayList<String>();
    
            //添加元素
            c.add("hello");
            c.add("world");
            c.add("java");
    
            //Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
            Iterator<String> it = c.iterator();       
            //用while循环改进判断
            while (it.hasNext()) {
                //System.out.println(it.next());
                String s = it.next();
                System.out.println(s);
            }
        }
    }
    

1.5、集合使用步骤图解【理解】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6xV60acs-1660040562543)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659940057849.png)]

Iterator< String > it = c.iterator();把集合中的数据复制了一份给迭代器对象。while这块首先有个东西指向了这个元素hello,然后it.hasNext();先判断此处是否有元素,有就执行String s = it.next();把当前的hello这个值拿出来给s,然后它本身再指向下一个地址。一直重复,直到指向的位置没有元素就结束。

1.6、集合的案例-Collection集合存储学生对象并遍历【应用】

  • 案例需求

    创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

  • 代码实现

    学生类

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    测试类

    /*
        需求:
            创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
    
        思路:
            1:定义学生类
            2:创建Collection集合对象
            3:创建学生对象
            4:把学生添加到集合
            5:遍历集合(迭代器方式)
     */
    public class CollectionDemo {
        public static void main(String[] args) {
            //创建Collection集合对象
            Collection<Student> c = new ArrayList<Student>();
    
            //创建学生对象
            Student s1 = new Student("林青霞", 30);
            Student s2 = new Student("张曼玉", 35);
            Student s3 = new Student("王祖贤", 33);
    
            //把学生添加到集合
            c.add(s1);
            c.add(s2);
            c.add(s3);
    
            //遍历集合(迭代器方式)
            //方式一:
            Iterator<Student> it = c.iterator();
            while (it.hasNext()) {
                Student s = it.next();
                System.out.println(s.getName() + "," + s.getAge());
            }
            //方式二:
            for (Student student : c) {
                System.out.println(student.getName()+ "," + student.getAge());
            }
    
        }
    }
    

2、List集合

2.1、List集合概述和特点【记忆】

List集合概述

  • 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素

  • 与Set集合不同,列表通常允许重复的元素

List集合特点

  • 有索引

  • 可以存储重复元素

  • 元素存取有序

2.2、List集合的特有方法【应用】

方法名描述
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素

2.3、集合的案例-List集合存储学生对象并遍历【应用】

案例需求

  • 创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

代码实现

  • 学生类

    代码同1.6学生类

  • 测试类同1.6测试类 把Collection改成List即可

2.4、并发修改异常【应用】

  • 出现的原因

    迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断预期修改值和实际 修改值不一致,则会出现:ConcurrentModifificationException

  • 解决的方案

    用for循环遍历,然后用集合对象做对应的操作即可

  • 示例代码

    public class ListDemo { 
        public static void main(String[] args) { 
            //创建集合对象 
            List<String> list = new ArrayList<String>(); 
            //添加元素 
            list.add("hello"); 
            list.add("world"); 
            list.add("java"); 
            //遍历集合,得到每一个元素,看有没有"world"这个元素,如果有,我就添加一 个"javaee"元素,请写代码实现 
            //报错:ConcurrentModifificationException
            /*Iterator<String> it = list.iterator(); 
            while (it.hasNext()) { 
            	String s = it.next(); 
            	if(s.equals("world")) { 
            		list.add("javaee"); 
            	} 
            }*/
            for(int i=0; i<list.size(); i++) { 
                String s = list.get(i);
                if(s.equals("world")) { 
                    list.add("javaee"); 
                } 
            }
            //输出集合对象 
            System.out.println(list); 
        } 
    }
    

2.5、列表迭代器【应用】

ListIterator介绍

  • 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器

  • 用于允许程序员沿任一方向遍历的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

示例代码

/*
    ListIterator:列表迭代器
        通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
        用于允许程序员沿任一方向遍历列表的列表的迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置

    ListIterator中的常用方法
        E next():返回迭代中的下一个元素
        boolean hasNext():如果迭代具有更多元素,则返回 true
        E previous():返回列表中的上一个元素
        boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true
        void add(E e):将指定的元素插入列表
 */
public class ListIteratorDemo {
    public static void main(String[] args) {
        //创建集合对象
        List<String> list = new ArrayList<String>();

        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");

        //输出集合对象
//        System.out.println(list);

        //迭代器的方式遍历
        ListIterator<String> it = list.listIterator();
        while (it.hasNext()) {
            String s = it.next();
            if (s.equals("world")){
                it.add("javaee");//若为list.add同样会报错
            }
            //System.out.println(s);
        }
        System.out.println(list);

    }
}

2.6、增强for循环【应用】

定义格式

for(元素数据类型 变量名 : 数组/集合对象名) { 
    循环体; 
}

示例代码

/*
    增强for:简化数组和Collection集合的遍历
        实现Iterable接口的类允许其对象成为增强型 for语句的目标
        它是JDK5之后出现的,其内部原理是一个Iterator迭代器

    格式:
        for(元素数据类型 变量名 : 数组或者Collection集合) {
            //在此处使用变量即可,该变量就是元素
        }
 */
public class ForDemo {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        for(int i : arr) {
            System.out.println(i);
        }
        System.out.println("--------");

        String[] strArray = {"hello","world","java"};
        for(String s : strArray) {
            System.out.println(s);
        }
        System.out.println("--------");

        List<String> list = new ArrayList<String>();
        list.add("hello");
        list.add("world");
        list.add("java");

        for(String s : list) {
            System.out.println(s);
        }
        System.out.println("--------");

        //内部原理是一个Iterator迭代器
        /*
        for(String s : list) {
            if(s.equals("world")) {
                list.add("javaee"); //ConcurrentModificationException
            }
        }
        */
    }
}

2.7、集合的案例-List集合存储学生对象三种方式遍历【应用】

案例需求

​ 创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

代码实现

​ 学生类 同上

​ 测试类

/*
    需求:
        创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:
        1:定义学生类
        2:创建List集合对象
        3:创建学生对象
        4:把学生添加到集合
        5:遍历集合
            迭代器:集合特有的遍历方式
            普通for:带有索引的遍历方式
            增强for:最方便的遍历方式
 */
public class ListDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<Student> list = new ArrayList<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);

        //把学生添加到集合
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //迭代器:集合特有的遍历方式
        Iterator<Student> it = list.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName()+","+s.getAge());
        }
        System.out.println("--------");

        //普通for:带有索引的遍历方式
        for(int i=0; i<list.size(); i++) {
            Student s = list.get(i);
            System.out.println(s.getName()+","+s.getAge());
        }
        System.out.println("--------");

        //增强for:最方便的遍历方式
        for(Student s : list) {
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}

2.8、数据结构

数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合

通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率

2.8.1、数据结构之栈和队列【记忆】

栈结构

  • 数据进入栈模型的过程称为:压/进栈
  • 数据离开栈模型的过程称为:弹/出栈

栈是一种数据先进后出的模型,如下图,进去的时候是A先进,出来的时候是D先出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6ZoKKYZ-1660040562543)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659944725578.png)]

队列结构

  • 数据从后端进入队列模型的过程称为:入队列
  • 数据从前端离开队列模型的过程称为:出队列

队列是一种数据先进先出的模型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LEqItunz-1660040562544)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659944901880.png)]

2.8.2、数据结构之数组和链表【记忆】

数组结构 :是一种查询快,增删慢的模型

  • 查询数据通过索引定位,查询任意数据耗时相同,查询效率高
  • 删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
  • 添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低

链表结构:查询慢、增删快

  • 链表可分为单向链表和双向链表。

  • 一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f0UiuKji-1660040562544)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659946756467.png)]

  • 一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VB132Npp-1660040562544)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659946776913.png)]

2.9、List集合的实现类

2.9.1、List集合子类的特点【记忆】

ArrayList集合

  • 底层是数组结构实现,查询快、增删慢

LinkedList集合

  • 底层是链表结构实现,查询慢、增删快
2.9.2、集合的案例-ArrayList集合存储学生对象三种方式遍历【应用】

案例需求

  • 创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

代码实现

/*
    需求:
        创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合

    思路:
        1:定义学生类
        2:创建ArrayList集合对象
        3:创建学生对象
        4:把学生添加到集合
        5:遍历集合
            迭代器:集合特有的遍历方式
            普通for:带有索引的遍历方式
            增强for:最方便的遍历方式
 */
public class ArrayListDemo {
    public static void main(String[] args) {
        //创建ArrayList集合对象
        ArrayList<Student> array = new ArrayList<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);

        //把学生添加到集合
        array.add(s1);
        array.add(s2);
        array.add(s3);

        //迭代器:集合特有的遍历方式
        Iterator<Student> it = array.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s.getName() + "," + s.getAge());
        }
        System.out.println("--------");

        //普通for:带有索引的遍历方式
        for(int i=0; i<array.size(); i++) {
            Student s = array.get(i);
            System.out.println(s.getName() + "," + s.getAge());
        }
        System.out.println("--------");

        //增强for:最方便的遍历方式
        for(Student s : array) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}
2.9.3、LinkedList集合的特有功能【应用】

特有方法

方法描述
public void addFirst(E e)元素添加到头部。
public void addLast(E e)元素添加到尾部。
public E removeFirst()删除并返回第一个元素。
public E removeLast()删除并返回最后一个元素。
public E getFirst()返回第一个元素。
public E getLast()返回最后一个元素。

3、Set集合

3.1、Set集合概述和特点【应用】

Set集合的特点

  • 元素存取无序

  • 没有索引、只能通过迭代器或增强for循环遍历

  • 不能存储重复元素

Set集合的基本使用

/*
    Set集合特点
        不包含重复元素的集合
        没有带索引的方法,所以不能使用普通for循环遍历

    HashSet:对集合的迭代顺序不作任何保证
 */
public class SetDemo {
    public static void main(String[] args) {
        //创建集合对象
        Set<String> set = new HashSet<String>();

        //添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        //不包含重复元素的集合
        set.add("world");

        //遍历
        for(String s : set) {
            System.out.println(s);
        }
    }
}
//结果为:
world
java
hello

3.2、哈希值【理解】

哈希值简介

  • 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

如何获取哈希值

  • Object类中的public int hashCode():返回对象的哈希码值

哈希值的特点

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的

  • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

获取哈希值的代码

  • 学生类 同上

  • 测试类

    /*
        哈希值:
            是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
    
        Object类中有一个方法可以获取对象的哈希值
            public int hashCode():返回对象的哈希码值
     */
    public class HashDemo {
        public static void main(String[] args) {
            //创建学生对象
            Student s1 = new Student("林青霞",30);
    
            //同一个对象多次调用hashCode()方法返回的哈希值是相同的
            System.out.println(s1.hashCode()); //1060830840
            System.out.println(s1.hashCode()); //1060830840
            System.out.println("--------");
    
            Student s2 = new Student("林青霞",30);
    
            //默认情况下,不同对象的哈希值是不相同的
            //通过方法重写,可以实现不同对象的哈希值是相同的
            System.out.println(s2.hashCode()); //2137211482
            System.out.println("--------");
    
            System.out.println("hello".hashCode()); //99162322
            System.out.println("world".hashCode()); //113318802
            System.out.println("java".hashCode()); //3254818
    
            System.out.println("world".hashCode()); //113318802
            System.out.println("--------");
    		//因为String类重写了hashcode方法,所以有可能导致两个字符串哈希值相同
            System.out.println("重地".hashCode()); //1179395
            System.out.println("通话".hashCode()); //1179395
        }
    }
    

3.3、HashSet集合概述和特点【应用】

HashSet集合的特点

  • 底层数据结构是哈希表

  • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致

  • 没有带索引的方法,所以不能使用普通for循环遍历

  • 由于是Set集合,所以是不包含重复元素的集合

HashSet集合的基本使用

/*
    HashSet集合特点
        1:底层数据结构是哈希表
        2:对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
        3:没有带索引的方法,所以不能使用普通for循环遍历
        4:由于是Set集合,所以是不包含重复元素的集合
 */
public class HashSetDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        HashSet<String> hs = new HashSet<String>();

        //添加元素
        hs.add("hello");
        hs.add("world");
        hs.add("java");

        hs.add("world");

        //遍历
        for(String s : hs) {
            System.out.println(s);
        }
    }
}

3.4、HashSet集合保证元素唯一性源码分析【理解】

HashSet集合保证元素唯一性的原理

  • 第一步:根据对象的哈希值计算存储位置

    • 如果当前位置没有元素则直接存入
    • 如果当前位置有元素存在,则进入第二步
  • 第二步:当前元素的元素和已经存在的元素比较哈希值

    • 如果哈希值不同,则将当前元素进行存储
    • 如果哈希值相同,则进入第三步
  • 第三步:通过equals()方法比较两个元素的内容

    • 如果内容不相同,则将当前元素进行存储
    • 如果内容相同,则不存储当前元素

HashSet集合保证元素唯一性的图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABZCJ5Qe-1660040562545)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1659951079652.png)]

3.5、常见数据结构之哈希表【理解】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TnP7bKmF-1660040562546)(D:\个人资料\java学习\问题及笔记\java常用类、集合、IO\assets\1660008159272.png)]

存储过程:HashSet默认初始容量为16。首先计算一个字符串在该HashSet的存储位置:即除以16取余。可以看到,hello、world、java取余都是2,首先存储hello,在2位置处没有元素,因此hello直接存储进去,接着存储world,发现在2位置处有元素,将world与2位置的所有元素进行对比,首先比较哈希值,发现哈希值不同则存储进去,java存储同理。接着再次在2位置存储world,发现2位置处已有元素,比较哈希值,发现有与world哈希值相同的元素,再比较对象的内容,发现内容也相同,尤其判断是重复元素,不予存储。

3.6、HashSet集合存储学生对象并遍历【应用】

案例需求

  • 创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合

  • 要求:学生对象的成员变量值相同,我们就认为是同一个对象

代码实现

学生类

public class Student {
    private String name;
    private int age;

    public Student() {
    }
    
    //此处省略get、set方法

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}

测试类

/*
    需求:
        创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
        要求:学生对象的成员变量值相同,我们就认为是同一个对象

    思路:
        1:定义学生类
        2:创建HashSet集合对象
        3:创建学生对象
        4:把学生添加到集合
        5:遍历集合(增强for)
 */
public class HashSetDemo02 {
    public static void main(String[] args) {
        //创建HashSet集合对象
        HashSet<Student> hs = new HashSet<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);

        Student s4 = new Student("王祖贤", 33);

        //把学生添加到集合
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        hs.add(s4);

        //遍历集合(增强for)
        for (Student s : hs) {
            System.out.println(s.getName() + "," + s.getAge());
        }
		
        HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");  // 重复的元素不会被添加
        System.out.println(sites);
    }
}

注:学生类中必须重写 equals和hashCode方法,否则测试时s4同样会被写进hs中,因为HashSet本身无法辨别以student创建的对象元素是否相同。若student类不重写两个方法,结果集hs会有两个“王祖贤”,而sites里却只有一个"Runoob"。

3.7、LinkedHashSet集合概述和特点【应用】

LinkedHashSet集合特点

  • 哈希表和链表实现的Set接口,具有可预测的迭代次序

  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的

  • 由哈希表保证元素唯一,也就是说没有重复的元素

LinkedHashSet集合基本使用

/*
    LinkedHashSet集合特点
        1:哈希表和链表实现的Set接口,具有可预测的迭代次序
        2:由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
        3:由哈希表保证元素唯一,也就是说没有重复的元素
 */
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();

        //添加元素
        linkedHashSet.add("hello");
        linkedHashSet.add("world");
        linkedHashSet.add("java");

        linkedHashSet.add("world");

        //遍历集合
        for(String s : linkedHashSet) {
            System.out.println(s);
        }
    }
}

3.8、Set集合排序

3.8.1、TreeSet集合概述和特点【应用】

TreeSet集合概述

  • 元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法

    • TreeSet():根据其元素的自然排序(数字从小到大字母从a到z)进行排序

    • TreeSet(Comparator comparator) :根据指定的比较器进行排序

  • 没有带索引的方法,所以不能使用普通for循环遍历

  • 由于是Set集合,所以不包含重复元素的集合

TreeSet集合基本使用

public class TreeSetDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Integer> ts = new TreeSet<Integer>();

        //添加元素
        ts.add(10);
        ts.add(40);
        ts.add(30);
        ts.add(50);
        ts.add(20);

        ts.add(30);

        //遍历集合
        for(Integer i : ts) {
            System.out.println(i);
        }
    }
}
// 结果:10 20 30 40 50   从小到大排列,并且不包含重复元素
3.8.2、自然排序Comparable的使用【应用】

案例需求

  • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法

  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

实现步骤

  • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的

  • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法

  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

代码实现

学生类

public class Student implements Comparable<Student> {
    private String name;
    private int age;

    // 省略get\set\有参\无参构造

    @Override
    public int compareTo(Student s) {
//        return 0; 0表示两者相等,则认为是重复数据不天剑
//        return 1; 1是正数,也可以是任意正数,表示后者比前者大,存储数据按照从前往后排列
//        return -1; -1也可以是任意负数,表示后者比前者小,存储数据按照从后往前排列
        //按照年龄从小到大排序
        //System.out.println("this:"+this.age+","+"s:"+s.age);
        int num = this.age - s.age; 
//        int num = s.age - this.age;
        //年龄相同时,按照姓名的字母顺序排序
        int num2 = num==0?this.name.compareTo(s.name):num;
        return num2;
    }
}

测试类:

/*
    存储学生对象并遍历,创建集合使用无参构造方法
    要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
 */
public class TreeSetDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<Student>();

        //创建学生对象
        Student s1 = new Student("xishi", 29);
        Student s2 = new Student("wangzhaojun", 28);
        Student s3 = new Student("diaochan", 30);
        Student s4 = new Student("yangyuhuan", 33);

        Student s5 = new Student("linqingxia",33);
        Student s6 = new Student("linqingxia",33);

        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);

        //遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}

注:int num = this.age - s.age中,this指的是每次新输入的年龄,s指的上一次做比较的年龄。

TreeSet比较流程:

​ (1)在第一次输入(“xishi”, 29)后,this.age=s.age=29,此时num=0,则执行this.name.compareTo(s.name),可得num2=0,保存(“xishi”, 29)数据;

​ (2)第二次输入(“wangzhaojun”, 28),this.age=28,s.age=29,此时num=-1,(“wangzhaojun”, 28)存储在(“xishi”, 29)前面

​ (3)第三次输入(“diaochan”, 30),this.age=30,s.age=29,此时num=1,(“diaochan”, 30)放到(“xishi”, 29)后面。

​ (4)第四次输入(“yangyuhuan”, 33),this.age=33,s.age=29,此时num=4,放到(“xishi”, 29)后面。但此时(“xishi”, 29)后已经有(“diaochan”, 30),因此两者要比较,此时s.age=30,与this.age=33比较,num=3,因此(“yangyuhuan”, 33)放到(“diaochan”, 30)后面。

​ (5)第五次输入(“linqingxia”,33),this.age=33,s从最开始取值,首先s.age=29,num=4,放(“xishi”, 29)后面;再s.age=30,num=3,放(“diaochan”, 30)后面;再s.age=33,比较名字,放(“yangyuhuan”, 33)前面。

​ (6)第六次输入(“linqingxia”,33),this.age=33,首先s.age=29,num=4,放(“xishi”, 29)后面;再s.age=30,num=3,放(“diaochan”, 30)后面;再s.age=33,比较名字,与前面保存的数据重复,不予保存。

3.8.3、比较器排序Comparator的使用【应用】

案例需求

  • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法

  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

实现步骤

  • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的

  • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法

  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

代码实现

学生类

public class Student {
    private String name;
    private int age;
    //省略无参/有参/get/set方法
}

测试类

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //this.age - s.age
                //s1,s2
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });

        //创建学生对象
        Student s1 = new Student("xishi", 29);
        Student s2 = new Student("wangzhaojun", 28);
        Student s3 = new Student("diaochan", 30);
        Student s4 = new Student("yangyuhuan", 33);

        Student s5 = new Student("linqingxia",33);
        Student s6 = new Student("linqingxia",33);

        //把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);

        //遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}
3.8.4、不重复的随机数案例【应用】
/*
    需求:
        编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出

    思路:
        1:创建Set集合对象
        2:创建随机数对象
        3:判断集合的长度是不是小于10
            是:产生一个随机数,添加到集合
            回到3继续
        4:遍历集合
 */
public class SetDemo {
    public static void main(String[] args) {
        //创建Set集合对象
//        Set<Integer> set = new HashSet<Integer>();
        Set<Integer> set = new TreeSet<Integer>();

        //创建随机数对象
        Random r = new Random();

        //判断集合的长度是不是小于10
        while (set.size()<10) {
            //产生一个随机数,添加到集合
            int number = r.nextInt(20) + 1;
            set.add(number);
        }

        //遍历集合
        for(Integer i : set) {
            System.out.println(i);
        }
    }
}

4、泛型

参考:Java中的包装类、泛型

4.1、泛型概述和好处【理解】

  • 泛型概述

    是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型。它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口

  • 泛型定义格式 : 泛型指的是在类定义时不明确类型,而在使用时明确类型。定义泛型使用"<>"操作符。

    • <类型>:指定一种类型的格式。这里的类型可以看成是形参

      • 称之为类型参数,可以使用任何字符,用中文都行,规范都是单个的大写字母。
        • T:表示任意类型
        • E:单个元素
        • K:键值对,key值
        • V:value值
    • <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参

    • 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型

  • 泛型的好处

    • 把运行时期的问题提前到了编译期间

    • 避免了强制类型转换

4.2、泛型类【应用】

定义格式

修饰符 class 类名<类型> { }

示例代码

  • 泛型类

    public class Generic<T> {
        private T t;
    
        public T getT() {
            return t;
        }
    
        public void setT(T t) {
            this.t = t;
        }
    }
    
  • 测试类

  • public class GenericDemo {
        public static void main(String[] args) {
            Student s = new Student();
            s.setName("林青霞");
            System.out.println(s.getName());
    
            Teacher t = new Teacher();
            t.setAge(30);
    //        t.setAge("30");
            System.out.println(t.getAge());
            System.out.println("--------");
    
            Generic<String> g1 = new Generic<String>();
            g1.setT("林青霞");
            System.out.println(g1.getT());
    
            Generic<Integer> g2 = new Generic<Integer>();
            g2.setT(30);
            System.out.println(g2.getT());
    
            Generic<Boolean> g3 = new Generic<Boolean>();
            g3.setT(true);
            System.out.println(g3.getT());
        }
    }
    

4.3、泛型方法【应用】

定义格式

修饰符 <类型> 返回值类型 方法名(类型 变量名) { }
public class Generic {
    public <T> void show(T t) {
        System.out.println(t);
    }
}
public class GenericDemo {
    public static void main(String[] args) {
        Generic g = new Generic();
        g.show("林青霞");
        g.show(30);
        g.show(true);
        g.show(12.34);
    }
}

4.4、泛型接口【应用】

定义格式

修饰符 interface 接口名<类型> { }
public interface Generic<T> {
    void show(T t);
}

一旦一个接口使用泛型声明,子类在实现接口时就有两种选择

a. 继续保留泛型

public class GenericImpl<T> implements Generic<T> {
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

b. 子类明确当前类型

public class GenericImpl02 implements Generic<String> {
    @Override
    public void show(String s) {
        System.out.println(s);
    }
}

测试:

public class GenericDemo {
    public static void main(String[] args) {
        Generic<String> g1 = new GenericImpl<String>();
        g1.show("林青霞");

        Generic<Integer> g2 = new GenericImpl<Integer>();
        g2.show(30);
        
        Generic<String> g3 = new GenericImpl02();//此时只能接受String类型
        g3.show("fdfasf");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值