Day13

一. StringBuffer

  1. 定义

    • 线程安全的可变字符序列, 一个类似于String的字符缓冲区, 我们可以将StringBuffer看作是一个高级的String
    • StringBuffer和String的区别
      • String是一个不可变的字符序列
      • StringBuffer是一个可变的字符序列
  2. 构造方法

    • public StringBuffer():无参构造方法 默认容量是16
    • public StringBuffer(int capacity):指定容量的字符串缓冲区对象
    • public StringBuffer(String str):指定字符串内容的字符串缓冲区对象
    • 扩容公式: 原容量<< 1 + 2
  3. 常用方法

    1. 容量和长度

      • public int capacity() : 返回当前容量 理论值(不掌握)

      • public int length() : 返回长度(字符数) 实际值

      • 演示

      public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer();
        //获取容量
        int capacity = buffer.capacity();
        //获取内容的长度
        int length = buffer.length();
            
        System.out.println(capacity);
        System.out.println(length);
      }
      
    2. 添加

      • public StringBuffer append(String str)

        • 可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
      • public StringBuffer insert(int offset,String str)

        • 在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身
        • 演示
      public static void main(String[] args) {
         StringBuffer buffer = new StringBuffer("abcd");
               
         buffer.append("abbc");
         System.out.println(buffer.toString());//结果:abcdabbc
               
         buffer.insert(2,"我爱你");//插入到指定位置
         System.out.println(buffer.toString());
      }
      
    3. 删除

      • public StringBuffer deleteCharAt(int index):
        • 删除指定位置的字符,并返回本身
      • public StringBuffer delete(int start,int end):
        • 删除从指定位置开始指定位置结束的内容,并返回本身
      • 演示
      public static void main(String[] args) {
       StringBuffer buffer = new StringBuffer("abcd");
           
       buffer.deleteCharAt(1);//删除角标为1的值
       System.out.println(buffer.toString());//结果:acd
           
       buffer.delete(1, 2);
       System.out.println(buffer.toString());//结果:ad
      }
      
    4. 替换和反转

      • public StringBuffer replace(int start,int end,String str)
        • 从start开始到end用str替换
      • public StringBuffer reverse()
        • 字符串反转
      • 演示
      public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer("abcd");
        //替换一部分内容
        buffer.replace(1, 3, "我爱你");
        System.out.println(buffer.toString());//结果:a我爱你d
        //反转
        buffer.reverse();
        System.out.println(buffer.toString());//结果:d你爱我a
      }
      
    5. 截取

      • public String substring(int start)
        • 从指定位置截取到末尾
      • public String substring(int start,int end):
        • 截取从指定位置开始到结束位置,包括开始位置,不包括结束位置
        • 注意: 返回值不再是StringBuffer本身,而是一个String
      • 演示
      public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer("abcdefg");
            
        //截取一部分,从某个角标开始,到结尾
        String s1 = buffer.substring(2);
        System.out.println(s1); //结果: cdefg
        //截取一段,从某个角标到某个角标 (不包尾)
        String s2 = buffer.substring(2,5);
        System.out.println(s2);//结果:cde
      }
      
    6. StringBuffer和String的相互转换

      1. String -- >StringBuffer
        • 通过构造方法
        • 通过StringBuffer的append方法
      2. StringBuffer --> String
        • 通过toString()方法
        • 通过subString(0,length)
  1. 案例

    1. 数组转成字符串

      • 需求: 使用StringBuffer将数组中的数据按照指定格式拼接成一个字符串
      • 输入结果: [ 1, 2, 3]
      public static void main(String[] args) {
              
        int[] arr = {6,5,8,7};
              
        StringBuffer buffer = new StringBuffer();
        buffer.append("[");
        for (int i = 0; i < arr.length; i++) {
          if (i==arr.length-1) {
            buffer.append(arr[i]).append("]");
          }else{
            buffer.append(arr[i]).append(",");
          }
        }
              
        System.out.println(buffer.toString());//结果: [6,5,8,7]
      }
      
    2. 字符串反转

      • 需求: 从键盘录入一个字符串,对字符串进行反转
      public static void main(String[] args) {
              
        Scanner scanner =new Scanner(System.in);
        String str = scanner.nextLine();
              
        StringBuffer buffer = new StringBuffer(str);
        buffer.reverse();
              
        System.out.println(buffer.toString());
              
        scanner.close();
      }
      

二. StringBuilder

  1. 定义

    StringBuilder功能等同于Stringbuffer, 线程不安全,效率高, 单线程下建议使用StringBuilder

  2. StringBuffer和StringBuilder的区别

    • StringBuffer是jdk1.0版本开始的,是线程安全的,效率低
    • StringBuilder是jdk1.5版本开始的,是线程不安全的,效率高

三. 基本数据类型的包装类

  1. 定义

    ​ 基本数据类型自身没有方法, 这样就限制了我们的使用, 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据

  2. 对应关系表

    基本数据类型 引用数据类型
    byte Byte
    short Short
    int Integer
    long Long
    float Float
    double Double
    char Character
    boolean Boolean
  3. 常用方法

    • 用于基本数据类型和字符串之间的转换
    public static void main(String[] args) {
     
     String str = "100";
     int num = Integer.parseInt(str);
     System.out.println(num*5); //结果: 500
    }
    
  4. 自动装箱和拆箱

    • 自动装箱: 把基本数据类型转换为包装类型
    • 自动拆箱: 把包装类型转换成基本数据类型
    public static void main(String[] args) {
     
     Integer ii = 100;//自动装箱
     int i = ii;     //自动拆箱
    }
    
    
  5. 测试题

    Integer i1 = new Integer(97);
    Integer i2 = new Integer(97);
    System.out.println(i1 == i2);
    System.out.println(i1.equals(i2));
    System.out.println("-----------");
    
    Integer i3 = new Integer(197);
    Integer i4 = new Integer(197);
    System.out.println(i3 == i4);
    System.out.println(i3.equals(i4));
    System.out.println("-----------");
    
    Integer i5 = 97;
    Integer i6 = 97;
    System.out.println(i5 == i6);
    System.out.println(i5.equals(i6));
    System.out.println("-----------");
    
    Integer i7 = 197;
    Integer i8 = 197;
    System.out.println(i7 == i8);
    System.out.println(i7.equals(i8));
    
    

四. Math

  1. 定义

    ​ Math类包含用于执行基本数学运算的方法, 如初等指数,对数,平方根和三角函数

  2. 常用方法

    • public static int abs(int a) : 返回一个数的绝对值
    • public static double ceil(double a) : 返回大于等于参数的最小整数
    • public static double floor(double a) : 返回小于等于参数的最大整数
    • public static int max(int a,int b) : 获取最大值
    • public static double pow(double a,double b) : 计算某个数的几次幂
    • public static double random() : 获取一个大于等于0且小于1的随机数
    • public static int round(float a) : 对象小数四舍五入
    • public static double sqrt(double a) : 计算平方根

五. Random

  1. 定义

    • 此类用于产生伪随机数
    • 之所以说是为随机数,是因为产生的数是使用一个算法算出的
    • 如果用相同的种子创建两个 Random 实例,则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列
  2. 构造方法

    • public Random()
    • public Random(long seed)
  3. 常用的方法

    • public int nextInt()
    • public int nextInt(int n)(重点掌握) : 产生一个0到参数(不包括)之内的随机整数
    public static void main(String[] args) {
     
     Random random = new Random();
     
     int num = random.nextInt(100);
     System.out.println(num);
    }
    
    
  4. 测试题

    随机生成一个4位整数的验证码

六. System

  1. 常用的方法

    • public static void gc() : 暗示垃圾回收器运行
    • public static void exit(int status) : 虚拟机退出
    • public static long currentTimeMillis() : 获取当前时间的毫秒值
    • pubiic static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) : 复制数组
  2. 演示

    public static void main(String[] args) {
     
     new Demo(); //创建一个匿名对象,当程序执行完这句话之后,这个对象就没用了
     System.gc();//暗示调用垃圾回收器 ,能不能回收,看脸
     
     long time = System.currentTimeMillis();//获取当前时间的毫秒值
     System.out.println(time);
     
     System.out.println("..........");
     System.exit(0); //退出jvm
     System.out.println(".........."); //将不会执行
    }
    
    

七. BigInteger

  1. 定义

    ​ 我们平时使用的数值类型都有一定的长度限制,当我们要运算的数超过了长度限制之后就无法使用了, 这时我们就可以使用BigInteger,他可以装载其他类型表示的任意长度的数值

  2. 构造方法

    • public BigInteger(String val)
  3. 成员方法

    • public BigInteger add(BigInteger augend) : 加
    • public BigInteger subtract(BigInteger subtrahend) : 减
    • public BigInteger multiply(BigInteger multiplicand) : 乘
    • public BigInteger divide(BigInteger divisor) : 除
    • public BigInteger[] divideAndRemainder(BigInteger val) : 返回除积和余数
  4. 演示

    public static void main(String[] args) {
     
     BigInteger bi = new BigInteger("10551020110102100");
     BigInteger bi2 = new BigInteger("100");
     
     System.out.println(bi.add(bi2));//10551020110102200
     System.out.println(bi.subtract(bi2));//10551020110102000
     System.out.println(bi.multiply(bi2));//1055102011010210000
     System.out.println(bi.divide(bi2));//105510201101021
    }
    
    

八. BigDecimal

  1. 定义

    • 由于在运算的时候,float类型和double很容易丢失精度,演示案例。
    • 所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal
    • 不可变的、任意精度的有符号十进制数。
  2. 构造方法

    • public BigDecimal(String val)
  3. 常用方法

    • public BigDecimal add(BigDecimal augend) : 加
    • public BigDecimal subtract(BigDecimal subtrahend) : 减
    • public BigDecimal multiply(BigDecimal multiplicand) : 乘
    • public BigDecimal divide(BigDecimal divisor) : 除
  4. 演示

    public static void main(String[] args) {
     
     BigDecimal b1 = new BigDecimal("2.0"); // 推荐使用传入字符串的形式
     BigDecimal b2 = new BigDecimal("1.1");
     
     System.out.println(b1.add(b2));//结果:3.1
     System.out.println(b1.subtract(b2));//结果:0.9
     System.out.println(b1.multiply(b2));//结果:2.20
     System.out.println(b1.divide(b2));//没有确定的结果
    }
    
    

九. Date

  1. 定义

    ​ Date类表示特定的瞬间, 精确到毫秒

  2. 构造方法

    • public Date()
    • public Date(long date)
  3. 常用方法

    • public long getTime()
    • public void setTime(long time)
  4. 演示

    public static void main(String[] args) {
     
     Date date = new Date();
     
     System.out.println(date.toString());//表示瞬时时间的字符串 结果: Mon Oct 30 22:50:48 CST 2017
     System.out.println(date.getTime());//获取瞬时时间的毫秒值  结果:1509375048974
     
     date.setTime(1509379011190L);//设置时间点 
     System.out.println(date.toString());//表示瞬时时间的字符串 结果:Mon Oct 30 23:56:51 CST 2017
     
    }
    
    

十. SimpleDateFormat(非常重要)

  1. 定义

    ​ 时间格式化工具,她以与语言无关的方式格式化并解析日期或时间

  2. 构造方法

    • public SimpleDateFormat()
    • public SimpleDateFormat(String pattern) 使用一个字符串时间格式
  3. 常用方法

    • public final String format(Date date)
    • public Date parse(String source)
  4. 时间格式标识符

    字母 日期或时间元素 表示 示例
    G Era 标志符 Text AD
    y Year 1996;96
    M 年中的月份 Month July;jul;07
    w 年中的周数 Number 27
    W 月份中的周数 Number 2
    D 年中的天数 Number 189
    d 月份中的天数 Number 10
    F 月份中的星期 Number 8
    E 星期中的天数 Text Tuesday;Tue
    a Am/pm 标记 Text PM
    H 一天中的小时数(0-23) Number 0
    k 一天中的小时数(1-24) Number 24
    K am/pm 中的小时数(0-11) Number 0
    h am/pm 中的小时数(1-12) Number 12
    m 小时中的分钟数 Number 30
    s 分钟中的秒数 Number 55
    S 毫秒数 Number 978
    z 时区 General time zone Pacific Standard Time;PST;GMT-08:00
    Z 时区 RFC 822 time zone -0800
  5. 演示

    public static void main(String[] args) throws ParseException {
     
     Date date = new Date();
     
     SimpleDateFormat dateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
     
     String format = dateFormat.format(date);
     System.out.println(format); // 结果: 2017-10-30 23:08:58
     
     Date date2 = dateFormat.parse("2017-05-1 10:13:22");//将字符串时间转成Date时间
     System.out.println(date2);//结果 : 2017-10-30 23:08:58
    }
    
    
  1. 测试题
    • 从键盘录入一个时间 xx年xx月xx日xx时xx分xx秒, 将这个时间转化成毫秒值保存下来

十一. Calendar(非常重要)

  1. 定义

    • Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法
    • Calendar 是一个万年历
  2. 成员方法

    • public static Calendar getInstance() 获取万年历对象
    • public int get(int field) 获取时间的某个值
    • public void add(int field,int amount) 在当前时间的基础上加上一段时间
    • public final void set(int year,int month,int date)设置时间点
  3. Calendar的时间字段

    • 具体查看API
    • 常用的字段
      • DAY_OF_MONTH 表示一个月中的某天
      • DAY_OF_WEEK表示一个星期中的某天
      • DAY_OF_YEAR表示当前年中的天数
      • HOUR_OF_DAY表示一天中的小时
      • YEAR表示年份
      • MONTH表示月份
      • WEEK_OF_MONTH 表示当前月中的星期数
  4. 演示

    public static void main(String[] args) throws ParseException {
     
     Calendar calendar = Calendar.getInstance(); //获取当前时间的日历对象
     
     System.out.println(calendar.getTime());//表示当前时间 结果:Mon Oct 30 23:26:47 CST 2017
     System.out.println(calendar.getTimeInMillis());//获取当前时间的毫秒值 结果:1509377207751
     
     calendar.add(Calendar.MONTH, 1);//给当前时间加1个月
     System.out.println(calendar.getTime());//结果: Thu Nov 30 23:28:16 CST 2017
     
     calendar.add(Calendar.MONTH, -2);//给当前时间减2个月
     System.out.println(calendar.getTime());//结果: Sat Sep 30 23:28:48 CST 2017
     
     calendar.set(Calendar.YEAR, 2015);//设置年份
     System.out.println(calendar.getTime());//结果: Wed Sep 30 23:29:41 CST 2015
     
     calendar.set(Calendar.MONTH, 3);//月份是从0开始的
     System.out.println(calendar.getTime());//结果: Thu Apr 30 23:33:32 CST 2015
     
     calendar.set(Calendar.DAY_OF_MONTH, 3);//设置日
     System.out.println(calendar.getTime());//结果: Fri Apr 03 23:35:05 CST 2015
    }
    
    
  5. 测试题

    • 需求: 从键盘录入一个年份,判断当年是闰年还是平年
    • 解题思路: 闰年的2月是29天 平年的2月是28天
    public static void main(String[] args) throws ParseException {
     
     Scanner scanner = new Scanner(System.in);
     System.out.println("请输入年份");
     int year = scanner.nextInt();
     
     Calendar calendar = Calendar.getInstance();
     calendar.set(year, 2, 1);//设置日期,某年的3月1日
     calendar.add(Calendar.DAY_OF_MONTH, -1);//将时间减1天,就变成了2月的最后一天
     int day = calendar.get(Calendar.DAY_OF_MONTH);//获取到这一天在当月中的数值
     if (day==29) {
         System.out.println("今年是闰年");
     }else{
         System.out.println("今年是平年");
     }
     scanner.close();
    }
    
    

总结

  1. StringBuffer (重中之重)
    • 是一个可变的字符序列
    • 其实就是一个可以改变长度的存放字符串的容器
    • 增 : append insert
    • 删 : deleteCharAt delete
    • 改 : setCharAt replace
    • 查 : charAt indexOf
  2. StringBuilder (和StringBuffer一样 )
    • 线程不安全, 效率高
  3. 基本数据类型的包装类(重点)
    • parseXXX()
  4. 其他类(不重要)
    • Math
    • System
    • BigInteger
    • BigDcimal
  5. Random(重点)
    • nextInt()
    • nextInt(b-a+1) +a (a-b 都包含)
    • nextInt(b-a) +a (a-b b包含)
  6. Date (重点)
    • 表示当前时间
    • getTime
    • setTime
  7. SimpleDateFormat(重点)
    • 时间格式化
    • format 将Date转成字符串
    • parse 将字符串转成Date
  8. Calendar (重中之重)
    • get
    • set
    • add

作业

  1. 第一题
    • 需求: 创建一个int型数组,从键盘录入数据,使用next()方法获取数据,存入数组中, 遍历数组
    • 注意: 对异常进行处理,循环录入, 直到输入"结束",终止程序,遍历数组
  2. 第二题
    • 需求: 从键盘录入一个字符串,判断字符串是否对称(使用StringBuffer和StringBuilder)
  3. 第三题(有漏洞,不准时replace())
    • 需求: 有一个字符串, 给字符串中所有字符 '我' 添加上引号
    • 示例: 我与父亲不想见已二年余了, 我最不能忘记的是他的背影
    • 结果: "我"与父亲不想见已二年余了, "我"最不能忘记的是他的背影
  4. 第四题
    • 需求: 从键盘录入两个时间, 计算这个两个时间之间相差的天数
    • 注意: 不足一天算一天
  5. 扩展题
    • 需求: 编写程序, 使用循环, 比较StringBuffer,StringBuilder和 + 之间的效率问题

一. 对象数组的概述和使用

  1. 案例演示

    • 需求: 创建5个学生对象, 将对象存入到数组中,遍历数组,打印学生信息

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n8" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    Student[] sts = new Student[5];

    sts[0] = new Student("小红", 18);
    sts[1] = new Student("小明", 19);
    sts[2] = new Student("小白", 20);
    sts[3] = new Student("小辉", 21);
    sts[4] = new Student("小张", 23);

    for (int i = 0; i < sts.length; i++) {
    System.out.println(sts[i]);
    }
    }</pre>

  2. 解析

    • 数组中存放的是对象的地址值

    • 遍历数组时就可以拿到引用地址值,调用对象完成方法

二. 集合概述

  1. 概述

    • 我们都知道,数组的长度是不可变的, 当元素的个数超过数组的长度之后, 我们就只能通过创建长度更长的新数组的方式来存储元素, 太麻烦了

    • 集合给我提供另外一种容器的概念,可变长度的容器, 这样,程序在使用的时候就不需要再考虑容器容量的问题,从而可以更加专心于业务

    • 我们要知道,java中数组是唯一的底层容器,所有, 集合是开发者使用java规范制作的逻辑上的容器

  2. 数组和集合的区别

    • 区别1

      • 数组既可以存储基本数据类型, 又可以储存引用数据类型,基本数据类型存储的是值, 引用数据类型储存的是地址值

      • 集合只能存储引用数据类型(对象的引用), 其实集合也可以存储基本数据类型, 但是在存储的时候自动装箱变成包装类对象

    • 区别2

      • 数组长度是固定的,不能自动增长

      • 集合的长度的是可变的,可以根据元素的增加而增长

  3. 使用场景

    • 如果元素的个数是固定的,推荐使用数组

    • 如果元素的个数不固定,推荐使用集合(日常开发中,使用集合比较普遍)

  4. 集合体系图

    [图片上传失败...(image-55d5cb-1575623003230)]

  5. 集合分类

    • Collection集合

      • 单列集合, 直接存储对象的引用
    • Map集合

      • 双列集合, 使用key-value的形式, 每个元素会有一个唯一的名称

三. Collection集合

  1. 定义

    • Collection是单列集合, 用于存储单个元素

    • Collection是一个接口, 他的下面有多个子接口和实现类, 我们称之为Collection体系

  2. 分类

    • List 集合中的元素是有序的,可以存放重复元素

    • Queue 队列, 除优先级外, 保持先进先出的原则(基本不用)

    • Set 集合中的元素是无序的, 不能存放重复的元素

  3. 体系图

  4. 常用方法

    • boolean add(E e) 添加元素

    • boolean remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话

    • void clear() 移除此 collection 中的所有元素

    • boolean contains(Object o) 判断集合中是否包含指定元素

    • boolean isEmpty() 判断集合中元素的个数是否为空

    • int size() 获取集合中元素的个数

  5. 案例演示

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n105" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    //如果没有泛型,会报出警告,不影响运行
    Collection<Student> collection = new ArrayList<>();

    Student student1 = new Student("小红", 18);
    Student student2 = new Student("小明", 19);

    collection.add(student1); //添加方法
    collection.add(student2);

    //判断集合中是否包含某个元素
    System.out.println(collection.contains(student1));//结果为 : true

    //判断集合中元素的个数是否为null
    System.out.println(collection.isEmpty());//结果: false

    //获取集合中元素的个数
    System.out.println(collection.size());//结果为 : 2

    //移除某个元素
    System.out.println(collection.remove(student2));//结果:true
    System.out.println(collection.size());//结果: 1

    //清空集合中的元素
    collection.clear();
    System.out.println(collection.size());//结果为0
    }</pre>

  6. 集合中所有带All的方法

    • boolean addAll(Collection c) 将指定 collection 中的所有元素都添加到此 collection 中

    • boolean removeAll(Collection c) 移除此 collection 中那些也包含在指定 collection 中的所有元素

    • boolean containsAll(Collection c) 如果此 collection 包含指定 collection 中的所有元素

    • boolean retainAll(Collection c) 仅保留此 collection 中那些也包含在指定 collection 的元素

    • 演示

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n119" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    Collection<Student> collection = new ArrayList<>();

    Student student1 = new Student("小红", 18);
    Student student2 = new Student("小明", 19);

    collection.add(student1); //添加方法
    collection.add(student2);

    Collection<Student> collection2 = new ArrayList<>();

    Student student3 = new Student("小辉", 18);
    collection2.add(student1);
    collection2.add(student3);

    //将collection2集合中的元素添加到collection集合中
    collection.addAll(collection2);
    System.out.println(collection.size());//结果: 4

    //判断collection集合中是否包含collection2集合中的所有元素
    boolean flg = collection.containsAll(collection2);
    System.out.println(flg);//结果: true

    //仅在collection中保留两个集合中相同的元素
    collection.retainAll(collection2);
    System.out.println(collection.size());//结果: 3
    }</pre>

四. 迭代器

  1. 定义

    • 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
  2. 案例演示遍历集合

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n129" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    Collection<Student> collection = new ArrayList<>();

    Student student1 = new Student("小红", 18);
    Student student2 = new Student("小明", 19);
    Student student3 = new Student("小辉", 18);

    collection.add(student1); //添加方法
    collection.add(student2);
    collection.add(student3);

    //集合转数组进行遍历
    Object[] obs= collection.toArray();

    for (int i = 0; i < obs.length; i++) {
    System.out.println(obs[i]); //前提集合内的元素重写了toString()方法
    }
    }</pre>

  3. 迭代器的遍历形式

    • 步骤

      • 获取迭代器

      • 调用hashNext()方法判断下一个元素是否存在

      • 调用next()方法获取元素

    • 演示

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n144" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    Collection<Student> collection = new ArrayList<>();

    Student student1 = new Student("小红", 18);
    Student student2 = new Student("小明", 19);
    Student student3 = new Student("小辉", 18);

    collection.add(student1); //添加方法
    collection.add(student2);
    collection.add(student3);

    //for循环的形式
    for(Iterator<Student> it = collection.iterator();it.hasNext();){
    Student student = it.next();
    System.out.println(student);
    }

    //while循环的形式
    Iterator<Student> it = collection.iterator();
    while(it.hasNext()){
    Student student = it.next();
    System.out.println(student);
    }
    }</pre>

  4. 迭代器工作原理

    • Iterator是一个接口,规定了迭代器的基本使用, 集合的子类都实现了迭代器方法, 同时返回属于自己的迭代器对象

    • 迭代器相当于是集合的一个副本, 里面记录了集合的基本属性值.

    • 使用时,我们先调用hashNext方法判断是否有下一个元素,如果有则返回true,否则返回false

    • 然后调用next()方法,返回当前指针所在位置上的元素

  5. 修改集合导致的异常

    • 当我们使用迭代器遍历集合的时候,如果对集合进行了修改,下一次循环会报错

    • 原因: 集合会记录修改的次数, 如果迭代器发现集合副本和原集合修改次数不一样的话就会报错

    • 解决办法: 使用迭代器的删除方法

    • 演示

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n167" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    Collection<Student> collection = new ArrayList<>();

    Student student1 = new Student("小红", 18);
    Student student2 = new Student("小明", 19);

    collection.add(student1); //添加方法
    collection.add(student2);

    //while循环的形式
    Iterator<Student> it = collection.iterator();
    while(it.hasNext()){
    Student student = it.next();
    //collection.remove(student);
    it.remove();
    }
    }</pre>

五. List集合

  1. 定义

    • List集合是有序的,可以储存重复的数据

    • List集合通过记录元素在集合中的位置来准确的查找元素

  2. List集合体系

    • ArrayList 底层使用数组(线程不安全)

    • LinkedList 底层使用链表

    • Vector 底层使用数组(线程安全的,不推荐使用)

六. ArrayList集合

  1. 定义

    • 低层使用的是数组, 所以其特性非常接近于数组

    • 储存的元素是有序的,而且可以重复存储, 通过数组角标来查询更改元素,速度非常快

    • 由于每次增删都要改动数组中的角标,所有导致增删效率低下

  2. ArrayList的增删改查原理

    • ArrayList 集合初始化会有一个默认长度是10的数组, 内部还有一个记录当前元素个数的变量, 当储存的元素个数超过数组长度之后,容量就会扩充一半

    • 当我们去查询集合中的元素时, 需要提供给集合一个角标值, 然后通过这个角标值查找集合中的元素

    • 当我们去删除一个元素的时候, 集合就会根据角标删除这个元素,并且改动其他元素的位置,这就是导致增删缓慢的原因

    • 其实如果我们是连续往集合尾部插入数据的话, 速度其实是非常快的, 因为其他元素的位置不需要改动,但是如果我们插入数据的位置是数组的前面或者中间,速度就会有明显的降低

  3. 构造方法

    • ArrayList() 构造一个初始化容量为10的空列表

    • ArrayList(Collection<? exends E> e) 构造一个包含执行集合元素的列表

    • ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表

  4. 常用方法

    • boolean add(E e) 将指定的元素添加到此列表的尾部

    • void add(int index,E element) 将指定的元素插入此列表中的指定位置

    • boolean contains(Object o) 如果此列表中包含指定的元素,则返回true

    • E get(int index) 通过角标查找元素

    • int indexOf(Object o) 返回此列表中首次出现的指定元素的索引, 或如果没有则返回 -1

    • int lastIndexOf(Object o) 返回此列表中最后一次出现的指定元素的索引(从后先前查)没有返回-1

    • boolean remove(Object o) 移除此列表中首次出现的指定元素(如果存在)

    • E set(int index , E element) 用指定元素替代此列表中指定位置上的元素,返回原来的元素

    • int size() 返回此列表中的元素数

  5. 演示

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n240" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

    //添加元素
    list.add("小红");
    list.add("小明");
    //将元素添加到角标1上
    list.add(1,"小辉");

    System.out.println(list.contains("小明"));//true

    //通过角标获取
    String str = list.get(1);
    System.out.println(str);//结果: 小辉

    //通过元素获取角标
    System.out.println(list.indexOf("小明"));//结果 : 2

    //通过角标移除元素
    System.out.println(list.remove(1));//结果: true

    //通过角标设置元素
    System.out.println(list.set(1, "小李"));//小辉

    }</pre>

  6. ArrayList集合的遍历

    • for 循环遍历, 基本上等同于数组

    • 演示

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="java" cid="n248" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

    list.add("小红");
    list.add("小明");
    list.add("小辉");

    for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
    }
    }</pre>

    • 迭代器 使用公用迭代器

    • 演示

    <pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n254" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

    list.add("小红");
    list.add("小明");
    list.add("小辉");
    
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        String str = it.next();
        System.out.println(str);
    }
    

    }
    </pre>

    • 迭代器2 List集合的迭代器(ListIterator) 可以从后往前遍历

    • 演示

    <pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n260" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

    list.add("小红");
    list.add("小明");
    list.add("小辉");
    
    ListIterator<String> it = list.listIterator();
    while (it.hasNext()) {
        String str = it.next();
        System.out.println(str);
    }
    
    while(it.hasPrevious()){
        String str = it.previous();
        System.out.println(str);
    }
    

    }
    </pre>

  7. 测试题

    • 去除集合中的重复字符串元素

    • 演示

    <pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n268" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    ArrayList list = new ArrayList();
    list.add("a");
    list.add("b");
    list.add("b");
    list.add("b");
    list.add("c");
    list.add("c");
    list.add("c");
    list.add("c");
    list.add("a");

    System.out.println(list);
    ArrayList newList = getSingle(list);
    System.out.println(newList);
    

    }
    </pre>

七. LinkedList集合

  1. 定义

    • 底层使用的是链表,就好像一条锁链

    • 这个集合中的每个元素都被封装到一个叫Node的内部类中, 然后记录上一个元素和下一个元素的地址,通过手拉手形成一个链条

    • 增删快, 查询慢

  2. 增删改查的原理

    • 当需要去查询LinkedList集合中的元素时,需要从最开始的元素查找起,然后一层一层往后找,直到找到该元素,这样的动作十分消耗性能

    • 当需要去删除元素的时候, 我们只需要将被删除元素两端的元素重新连接到一起,或者新增的时候将新元素和左右两边的元素连起来就可以了

  3. 构造方法

    • LinkedList() 构造一个空列表

    • LinkedList(Collection<? extends E> e) 构造一个包含指定collection中元素的列表

  4. 常用方法

    • E remove() 获取并移除此列表的头

    • E poll() 获取并移除此列表的头

    • E peek() 获取但不移除此列表的头

  5. 演示

    <pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n305" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">public static void main(String[] args) {
    LinkedList<String> list = new LinkedList<>();

    list.add("小红");
    list.add("小明");
    list.add("小辉");
    
    System.out.println(list.remove());//结果: 小红
    System.out.println(list.size());//结果:2
    
    System.out.println(list.poll());//结果: 小明
    System.out.println(list.size());//结果:1
    
    System.out.println(list.peek());//结果: 小辉
    System.out.println(list.size());//结果:1
    

    }
    </pre>

八. ArrayList, LinkedList 及Vector集合之间的区别

  1. 线程安全

    • Vector : 线程安全

    • ArrayList, LinkedList : 线程不安全

  2. 实现方式

    • LinkedList : 链表

    • ArrayList,Vector : 数组

  3. 扩容

    • ArrayList和Vector使用数组实现, 当数组长度不够,内部会创建一个更大的数组

    • LinkedList 不存在这方面的问题

  4. 速度

    • ArrayList 查改块, 增删慢

    • LinkedList 查改慢, 增删快

总结

  1. StringBuffer和StringBuilder

    • 高级的字符串, 可以变长度的字符序列

    • StringBuffer安全效率低, StringBuilder不安全,效率高

  2. 包装类

    • 八个基本数据类型的包装类

    • 自动装箱和自动拆箱

    • 每个包装类中都有一个可以将字符串转成基本数据类型的方法 xxx.parseXXX();

  3. Random

    • 生成随机数

    • nextInt()

    • nextInt(int num)

    • 生成一个a - b(包含a,不包含b的随机数) nextInt(b-a)+a;

    • 生成一个a - b(包含a,包含b的随机数) nextInt(b-a+1)+a;

  4. 集合

    • ArrayList 底层数组 增删慢 查改块

    • LinkedList底层链表 增删块 查改慢

    • 这里的增指的是 插入 , 实际上如果是尾部添加, ArrayList反而更块

作业

  1. 第一个题

    • 需求: 定义一个swap()方法,传入集合和两个角标,将两个角标上的元素交换位置
  2. 第二题

    • 需求: 创建一个Student类,定义name和age属性,创建几个Student对象放入集合中,遍历集合,查找年龄最大的对象,并打印
  3. 第三题

    • 需求: 定义集合让集合中添加多个元素,然后将集合中的元素位置反转
  4. 第四题

    • 需求: 创建一个Student类,定义name和age属性, 创建几个对象存入集合中(有重复属性的对象),创建方法去除集合中的重复元素
  5. 扩展题

    • 第一题

      • 需求: 现在有16只球队, 科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚、日本,美国,中国,新西 兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利. 将这16只球队存入到集合中,然后随机分成4组存入到4个集合中.遍历打印集合
    • 第二题

      • 需求: 创建一个Student类, 定义 姓名,年龄,班级,成绩 属性, 然后创建多个对象存入集合中, 求出所有学生的平均年龄和每个班级的平均成绩

      • Student类的属性如下所示

      <pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="java" cid="n415" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; background: rgb(51, 51, 51); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"> private String name;
      private int age;
      private int score;
      private String ClassNum;
      </pre>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,369评论 0 4
  • 一. Java基础部分.................................................
    wy_sure阅读 3,805评论 0 11
  • JAVA面试题 1、作用域public,private,protected,以及不写时的区别答:区别如下:作用域 ...
    JA尐白阅读 1,146评论 1 0
  • 小编费力收集:给你想要的面试集合 1.C++或Java中的异常处理机制的简单原理和应用。 当JAVA程序违反了JA...
    八爷君阅读 4,580评论 1 114
  • 拼命 最糟糕的努力姿势 叶老师说得没有错,但是现实还是有点困难,我想应该正确看待,循序渐进,争取做到早睡早起,不...
    无糖咖啡沈1阅读 152评论 0 1