Java学习笔记(第12章 P444-P459)(第13章P460-P498)(第14章P499-P553)

  • 第12章 异常-Exception
    • 异常介绍
    • 编译异常
    • 异常处理
      • try-catch异常处理
      • throws异常处理
    • 自定义异常
    • throw 和 throws 的区别
  • 第13章 常用类
    • 包装类(Wrapper)
      • 包装类类型和String类型的相互转换
      • Integer类和Character类的常用方法
      • Integer类面试题
    • String类
      • 字符串的特性
      • String类的常见方法
    • StringBuffer类
      • String和StringBuffer相互转换
      • StringBuffer类常见方法
    • StringBuilder类
      • String、StringBuffer 和 StringBuilder的比较
    • Math类
    • Arrays类
    • System类
    • BigInteger和BigDecimal类
    • 日期类
      • 第一代日期类
      • 第二代日期类
      • 第三代日期类
    • 章节作业
  • 第14章 集合
    • 集合的理解和好处
    • 集合的框架体系
    • Collection接口和常用方法
    • List接口和常用方法
    • ArrayList底层结构和源码分析
    • Vector底层结构和源码剖析
    • LinkedList底层结构
    • Set接口和常见方法
      • Set接口实现类-HashSet
      • Set接口实现类-LinkedHashSet
    • Map接口的常用方法
      • Map接口实现类- HashMap
      • Map接口实现类- Hashable
      • Map接口实现类-Properties
    • Treeset的相关用法
    • 总结-开发中如何选择集合实现类(记住)
    • Collections工具类
    • 章节作业
  • 日期

第12章 异常-Exception

异常介绍

  • 基本概念
    Java语言中,将程序执行中发生的不正常情况称为"异常"。(开发过程中的语法错位和逻辑错误不是异常)

  • 执行过程中所发生的异常事件可分为两大类

    1)Error(错误):java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError【栈溢出】和OOM(out of memory),Error是严重错误,程序会崩溃
    2)Exception:其它因编译错误或偶然的外在因素导致的一般性问题,可以使用针对的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception分为两大类:运行时异常[程序运行时,发生的异常]和编译时异常[编程时,编译器检查出的异常]。

  • 异常体系图

  • 异常体系图的小结
    1.异常分为两大类,运行时异常和编译时异常
    2.运行时异常,编译器检查不出来。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常
    3.对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响
    4.编译时异常,是编译器要求必须处置的异常。

  • 常见的运行时异常
    1)NullPointerException空指针异常
    当应用程序试图在需要对象的地方使用null时,抛出该异常
    2)ArithmeticException数字运算异常
    当出现异常的运算条件时,抛出该异常(整数除以零)
    3)ArrayIndexOutOfBoundsException数组下标越界异常
    用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引
    4)ClassCastException类型转换异常
    当试图将对象强制转换为不是实例的子类时,抛出该异常。
    5)NumberFormatException数字格式不正确异常
    当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出异常=>使用异常我们可以确保输入是满足条件数字

编译异常

  • 介绍
    编译异常是指编译期间,就必须处理的异常,否则代码不能通过编译。

-常见的编译异常
√SQLException //操作数据库时,查询表可能发生异常
√IOException //操作文件时,发生的异常
√FileNotFoundException //当操作一个不存在的文件时,发生异常
√ClassNotFoundException //加载类,而该类不存在时,异常
√EOFException //操作文件,到文件末尾,发生异常
√IlleglArguementException //参数异常

异常处理

  • 基本介绍
    异常处理就是当异常发生时,对异常处理的方式

  • 异常处理的方式
    1)try- catch-finally
    程序员在代码中捕获发生的异常,自行处理
    2)throws
    将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

  • 示意图

try-catch异常处理

  • try-catch方式处理异常说明

1)Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个try…catch块
2)基本语法

try{//可疑代码//将异常生成对应的异常对象,传递给catch块
}catch(异常){//对异常处理
}
//如果没有finally,语法是可以通过的
  • try- catch方式处理异常
    1)如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块
    2)如果异常没有发生,则顺序执行try的代码块,不会进入到catch
    3)如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)
    则使用如下代码-finally{}
    4)可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointException在前),如果发生异常,只会匹配一个catch
    5)可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑
try{//代码...
}
finally{    //总是执行
}
  • try- catch- finally执行顺序小结
    1)如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally里面的语句
    2)如果出现异常,则try块中异常发生后,try块剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句!

  • try-catch异常处理案例
    要求:如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止

实现代码:

package com.hspedu.try_;import java.util.Scanner;public class TryCatchExercise04 {public static void main(String[] args) {//如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止//思路//1.创建Scanner对象//2.使用无限循环,去接收一个输入//3.然后将该输入的值,转成一个int//4.如果在转换时,抛出异常,说明输入的内容不是一个可以转成int的内容//5.如果没有抛出异常,则break 该循环Scanner scanner = new Scanner(System.in);int num = 0;String inputStr = "";while(true){System.out.println("请输入一个整数:");inputStr = scanner.next();try {num = Integer.parseInt(inputStr);   //这里是可能抛出异常break;} catch (NumberFormatException e) {System.out.println("你输入的不是一个整数:");}}System.out.println("你输入的值是=" + num);}
}

throws异常处理

  • 基本介绍
    1)如果一个方法(中语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
    2)在方法声明中用throws语句可以声明抛出异常的列表(即多个异常),throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

  • 注意事项和使用细节
    1)对于编译异常,程序中必须处理,比如try-catch或者throws
    2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
    3)子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
    4)在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws

自定义异常

  • 基本概念
    当程序中出现了某些"错误",但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。

  • 自定义异常的步骤
    1)定义类:自定义异常类名(程序员自己写)继承Exception或RuntimeException
    2)如果继承Exception,属于编译异常
    3)如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)

补充:
1.一般情况下,我们自定义异常是继承RuntimeException
2.即把自定义异常做成运行时异常,好处是,我们可以使用默认的处理机制

throw 和 throws 的区别

  • 一览表

第13章 常用类

包装类(Wrapper)

1)针对八种基本数据类型相应的引用类型–包装类
2)有了类的特点,就可以调用类中的方法

  • 包装类和基本数据的转换
    1)jdk5前的手动装箱和拆箱方式,装箱:基本类型->包装类型,反之,拆箱
    2)jdk5以后(含jdk5)的自动装箱和拆箱方式
    3)自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
    4)其他包装类的用法类似,不一一举例
public class Integer01 {public static void main(String[] args) {//演示int <--> Integer 的装箱和拆箱//jdk5前是手动装箱和拆箱//手动装箱int n1 = 100;Integer integer = new Integer(n1);Integer integer1 = Integer.valueOf(n1);//手动拆箱//Integer -> intint i = integer.intValue();//jdk5后,就可以自动装箱和自动拆箱int n2 = 200;//自动装箱 int -> IntegerInteger integer2 = n2;     //底层使用的是 Integer.valueOf(n2)//自动拆箱 Integer -> intint n3 = integer2;  //底层仍然使用的是 intValue()方法}
}

包装类类型和String类型的相互转换

public class WrapperVSString {public static void main(String[] args) {//包装类(Integer) -> StringInteger i = 100;//方式1String str1 = i + "";//方式2String str2 = i.toString();//方式3String str3 = String.valueOf(i);//String -> 包装类(Integer)String str4 = "12345";Integer i2 = Integer.parseInt(str4);      //使用到自动装箱Integer i3 = new Integer(str4);     //构造器System.out.println("ok~~");}
}

Integer类和Character类的常用方法

public class WrapperMethod {public static void main(String[] args) {System.out.println(Integer.MIN_VALUE); //返回最小值System.out.println(Integer.MAX_VALUE);//返回最大值System.out.println(Character.isDigit('a'));//判断是不是数字System.out.println(Character.isLetter('a'));//判断是不是字母System.out.println(Character.isUpperCase('a'));//判断是不是大写System.out.println(Character.isLowerCase('a'));//判断是不是小写System.out.println(Character.isWhitespace('a'));//判断是不是空格System.out.println(Character.toUpperCase('a'));//转成大写System.out.println(Character.toLowerCase('A'));//转成小写}
}

Integer类面试题

题中System.out.println输出了什么
1.

public class WrapperExercise02 {public static void main(String[] args) {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j);  //False//所以,这里主要是看范围 -128 ~ 127 就是直接返回/*//1. 如果i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回//2. 如果不在 -128~127,就直接 new Integer(i)//源码:public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}*/Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码Integer n = 1;//底层 Integer.valueOf(1);System.out.println(m == n); //T//所以,这里主要是看范围 -128 ~ 127 就是直接返回//,否则,就new Integer(xx);Integer x = 128;//底层Integer.valueOf(1);Integer y = 128;//底层Integer.valueOf(1);System.out.println(x == y);//False}
}
public class WrapperExercise03 {public static void main(String[] args) {//示例一Integer i1 = new Integer(127);Integer i2 = new Integer(127);System.out.println(i1 == i2);//F//示例二Integer i3 = new Integer(128);Integer i4 = new Integer(128);System.out.println(i3 == i4);//F//示例三Integer i5 = 127;//底层Integer.valueOf(127)Integer i6 = 127;//-128~127System.out.println(i5 == i6); //T//示例四Integer i7 = 128;Integer i8 = 128;System.out.println(i7 == i8);//F//示例五Integer i9 = 127; //Integer.valueOf(127)Integer i10 = new Integer(127);System.out.println(i9 == i10);//F//示例六Integer i11=127;int i12=127;//只有有基本数据类型,判断的是//值是否相同System.out.println(i11==i12); //T//示例七Integer i13=128;int i14=128;System.out.println(i13==i14);//T}
}

String类

  • String类的理解和创建对象
  1. String对象用于保存字符串,也就是一组字符序列
  2. 字符串常量对象是用双引号括起的字符序列。例如:“你好”、“12.97”、"boy"等
  3. 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节。
  4. String类较常用构造器(其它看手册):
    String s1 = new String();
    String s2 = new String(String original);
    String s3 = new String(char[] a);
    String s4 = new String(char[] a, int startIndex, int count)
  5. String 类实现了接口 Serializable【String 可以串行化:可以在网络传输】,接口 Comparable [String 对象可以比较大小]
  6. String 是 final类 ,不能被其他的类继承
  7. String 有属性 private final char value[];用于存放字符串内容
  8. 一定要注意: value 是一个final类型, 不可以修改(需要理解):即value不能指向新的地址,但是单个字符内容是可以变化
  • 创建String对象的两种方式
    1)方式一:直接赋值 String s = “hspedu”;
    2)方式二:调用构造器String s = new String(“hspedu”);

  • 两种创建String对象的区别
    1.方式一:先从常量池查看是否有"hsp"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址
    2.方式二:现在堆中创建空间,里面维护了value属性,指向常量池的hsp空间。如果常量池没有"hsp",重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
    3.两种方式的内存分布图

    实例1:

public class StringExercise01 {public static void main(String[] args) {String a = "abc";String b = "abc";System.out.println(a.equals(b));    //TSystem.out.println(a == b);     //T}
}


实例2:

public class StringExercise03 {public static void main(String[] args) {String a = "hsp"; //a 指向 常量池的 “hsp”String b =new String("hsp");//b 指向堆中对象System.out.println(a.equals(b)); //TSystem.out.println(a==b); //F//b.intern() 方法返回常量池地址System.out.println(a==b.intern()); //T //intern方法自己先查看APISystem.out.println(b==b.intern()); //F}
}

  • 知识点:
    当调用intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此对象的引用
    解读:b.intern()方法最终返回的是常量池的地址(对象)

实例3:

public class StringExercise05 {public static void main(String[] args) {Person p1 = new Person();p1.name = "hspedu";Person p2 = new Person();p2.name = "hspedu";System.out.println(p1.name.equals(p2.name));//比较内容: TrueSystem.out.println(p1.name == p2.name);  //TSystem.out.println(p1.name == "hspedu");   //TString s1 = new String("bcde");String s2 = new String("bcde");System.out.println(s1==s2); //False}
}
class Person {public String name;
}

字符串的特性

1)String是一个final类,代表不可变的字符序列
2)字符串是不可变的。一个字符串对象一旦分配,其内容是不可变的。

  • 面试题
    1)题1
    图解:

    2)题二

    3)题三
  1. 题四


示意图
代码:

public class StringExercise10 {}class Test1 {String str = new String("hsp");final char[] ch = {'j', 'a', 'v', 'a'};public void change(String str, char ch[]) {str = "java";ch[0] = 'h';}public static void main(String[] args) {Test1 ex = new Test1();ex.change(ex.str, ex.ch);System.out.print(ex.str + " and ");System.out.println(ex.ch);}
}

运行结果:

String类的常见方法

  • 说明
    String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低n因此java设计者还提供了StringBuilder和StringBuffer来增强String的功能,并提高效率。

  • String类的常见方法一览

  1. equals //区分大小写,判断内容是否相等
  2. equalsIgnoreCase //忽略大小写的判断内容是否相等
  3. length //获取字符的个数,字符串的长度
  4. indexOf //获取字符在字符串中第一次出现的索引,索引从0开始,如果找不到,返回-1
  5. lastIndexOf //获取字符在字符串最后1次出现的索引,索引从0开始,如找不到,返回-1
  6. substring //截取指定范围的子串
  7. trim //去前后空格
  8. charAt //获取某索引处的字符,注意不能使用Str[index]这种方式
    String str = “hello”;
    //str[0]不对
    //str.charAt(0) => h

案例演示String另一组相关的方法:

public class StringMethod02 {public static void main(String[] args) {// 1.toUpperCase转换成大写String s = "heLLo";System.out.println(s.toUpperCase());    //HELLO// 2.toLowerCaseSystem.out.println(s.toLowerCase());    //hello// 3.concat拼接字符串String s1 = "宝玉";s1 = s1.concat("林黛玉").concat("薛宝钗").concat("together");System.out.println(s1);     //宝玉林黛玉薛宝钗together// 4.replace 替换字符串中的字符s1 = "宝玉 and 林黛玉 林黛玉 林黛玉";//在s1中,将所有的 林黛玉 替换成薛宝钗//  s1.replace()方法执行后,返回的结果才是替换过的.// 注意对 s1没有任何影响String s11 = s1.replace("林黛玉", "薛宝钗");System.out.println(s1);     //宝玉 and 林黛玉 林黛玉 林黛玉System.out.println(s11);    //宝玉 and 薛宝钗 薛宝钗 薛宝钗// 5.split 分割字符串,对于某些分割字符,我们需要转义比如| \\等String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";//1. 以 ,为标准对poem进行分割 , 返回一个数组//2. 在对字符串进行分割时, 如果有特殊字符,需要加入 转义符 \String[] split = poem.split(",");poem = "E:\\aaa\\bbb";split = poem.split("\\\\");System.out.println("===分割后内容===");for(int i = 0; i < split.length; i++){System.out.println(split[i]);}// 6.toCharArray 转换成字符数组s = "happy";char[] chs = s.toCharArray();for(int i = 0; i < chs.length; i++){System.out.println(chs[i]);}// 7.compareTo 比较两个字符串的大小,如果前者大,// 则返回正数,后者大,则返回负数, 如果相等, 返回0// (1) 如果长度相同,并且每个字符也相同,就返回0// (2) 如果长度相同或者不相同,但是在进行比较时,可以区分大小//     就返回  if (c1 != c2) {//                return c1 - c2;//            }// (3) 如果前面的部分都相同,就返回 str1.len - str2.lenString a = "jcck";String b = "jack";System.out.println(a.compareTo(b));     //返回值是 'c' - 'a' = 2的值//8.format格式字符串/* 占位符有:* %s字符串 %c 字符 %d 整型 %.2f 浮点型**/String name = "john";int age = 10;double score = 56.857;char gender = '男';//将所有的信息都拼接在一个字符串。String info ="我的姓名是" + name + "年龄是" + age + ",成绩是" + score + "性别是" + gender + ".希望大家喜欢我!";System.out.println(info);//1. %s , %d, %.2f, %c 称为占位符//2. 这些占位符由后面变量来替换//3. %s 表示后面 字符串来替换//4. %d 是正数来替换//5. %.2f 表示使用小数来替换, 替换后, 只会保留小数点两位, 并且进行四舍五入的处理//6. %c 使用char类型来替换String formatStr = "我的名字是%s年龄是%d,成绩是%.2f性别是%c.希望大家喜欢我!";String info2 = String.format(formatStr, name, age, score, gender);System.out.println("info2=" + info2);}
}

输出:

StringBuffer类

  • 基本介绍
    java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。
    很多方法与String相同,但StringBuffrt是可变长度的。
    StringBuffer是一个容器。
  1. StringBuffer 的直接父类 是 AbstractStringBuilder
  2. StringBuffer 实现了 Serializable, 即StringBuffer的对象可以串行化
  3. 在父类中 AbstractStringBuilder 有属性 char[] value, 不是final
    该value 数组存放 字符串内容 , 引出存放在堆中的
  4. StringBuffer 是一个final类,不能被继承
  5. 因为StringBuffer字符内容是存放在 char[] value, 所有在变化(增加/删除)不用每次都更换地址(既不是每次创建新对象),所以效率高于String
  • String VS StringBuffer
    1)String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低(private final char value[];)
    2)StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高(char[] value;//这个放在堆)

  • StringBuffer的构造器
    √构造器的使用

public class StringBuffer02 {public static void main(String[] args) {//构造器的使用//1.创建一个大小为16的char[] ,用于存放字符内容StringBuffer stringBuffer = new StringBuffer();//2.通过构造器指定 char[] 大小StringBuffer stringBuffer1 = new StringBuffer(100);//3.通过给一个String创建StringBuffer, char[] 大小就是 str.length() + 16StringBuffer hello = new StringBuffer("hello");}
}

String和StringBuffer相互转换

public class StringAndStringBuffer {public static void main(String[] args) {//看 String-->StringBufferString str = "hello tom";//方式1 使用构造器//注意: 返回的才是StringBuffer对象.对str本身没有影响StringBuffer stringBuffer = new StringBuffer(str);//方式2 使用的是append方法StringBuffer stringBuffer1 = new StringBuffer();stringBuffer1 = stringBuffer1.append(str);//看看 StringBuffer -> StringStringBuffer stringBuffer3 = new StringBuffer("韩顺平教育");//方式1 使用StringBuffer提供的 toString方法String s = stringBuffer3.toString();//方式2 使用构造器来搞定String s1 = new String(stringBuffer3);}
}

StringBuffer类常见方法

1)增append
2)删delete(start,end)
3)改replace(start,end,string) //将start—end间的内容替换掉,不含end
4)查indexOf //查找子串在字符串第1次出现的索引如果找不到返回-1
5)插insert
6)获取长度length

实例:

public class StringBufferMethod {public static void main(String[] args) {StringBuffer s = new StringBuffer("hello");//增s.append(',');// "hello,"s.append("张三丰");//"hello,张三丰"s.append("赵敏").append(100).append(true).append(10.5);//"hello,张三丰赵敏100true10.5"System.out.println(s);//"hello,张三丰赵敏100true10.5"//删/** 删除索引为>=start && <end 处的字符* 解读: 删除 11~14的字符 [11, 14)*/s.delete(11, 14);System.out.println(s);//"hello,张三丰赵敏true10.5"//改//使用 周芷若 替换 索引9-11的字符 [9,11)s.replace(9, 11, "周芷若");System.out.println(s);//"hello,张三丰周芷若true10.5"//查找指定的子串在字符串第一次出现的索引,如果找不到返回-1int indexOf = s.indexOf("张三丰");System.out.println(indexOf);//6//插//在索引为9的位置插入 "赵敏",原来索引为9的内容自动后移s.insert(9, "赵敏");System.out.println(s);//"hello,张三丰赵敏周芷若true10.5"//长度System.out.println(s.length());//22System.out.println(s);}
}

StringBuilder类

  • 基本介绍
    1)一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步(StringBuilder不是线程安全)。该类被被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,他比StringBuffer要快。
    2)在StringBuilder上的主要操作是append和insert方法,可重载这些方法,以接受任意类型的数据。

  • StringBuilder常用方法
    StringBuilder和StringBuffer均代表可变的字符序列.方法是一样的,所以使用和StringBuffer一样

√StringBuilder相关说明:

public class StringBuilder01 {public static void main(String[] args) {//1.StringBuilder 继承 AbstractStringBuilder 类//2. 实现了 Serializable ,说明StringBuilder对象是可以串行化(对象可以网络传输,可以保存到文件)//3. StringBuilder 是final类,不能被继承//4. StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder的 char[] value;//      因此,字符序列是堆中//5. StringBuilder 的方法, 没有做互斥的处理,即没有synchronized 关键字,因此在单线程的情况下使用//      StringBuilderStringBuilder stringBuilder = new StringBuilder();}
}

String、StringBuffer 和 StringBuilder的比较

1)StringBuilder和StringBuffer非常类似,均代表可变的字符序列,而且方法也一样。
2)String:不可变字符序列,效率低,但是复用率高
3)StringBuffer: 可变字符序列、效率较高(增删)、线程安全,看源码
4)StringBuilder:可变字符序列、效率最高、线程不安全
5)String使用注意说明:
string s = “a”; //创建了一个字符串
s += “b”; //实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s += “b”(也就是"ab")。如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能=>结论:如果我们对String做大量修改,不要使用String

  • String、StringBuffer 和 StringBuilder的效率测试
    效率:StringBuilder > StringBuffer > String

  • String、StringBuffer 和 StringBuilder的选择
    使用的原则,结论:

  1. 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder
  2. 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder
  3. 如果字符串存在大量的修改操作.并在多线程的情况,使用StringBuffer
  4. 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等

Math类

  • 基本介绍
    Math类包含用于执行基本数学运算,如初等指数、对数、平方根和三角函数。
  • 方法一览(均为静态方法)
  • Math类常见方法应用案例
public class MathMethod {public static void main(String[] args) {//看看Math常用的方法(静态方法)//1.abs 绝对值int abs = Math.abs(-9);System.out.println(abs);//9//2.pow 求幂double pow = Math.pow(2, 4);//2的4次方System.out.println(pow);//16//3.ceil 向上取整,返回>=该参数的最小整数(转成double);double ceil = Math.ceil(3.9);System.out.println(ceil);//4.0//4.floor 向下取整,返回<=该参数的最大整数(转成double)double floor = Math.floor(4.001);System.out.println(floor);//4.0//5.round 四舍五入  Math.floor(该参数+0.5)long round = Math.round(5.51);System.out.println(round);//6//6.sqrt 求开方double sqrt = Math.sqrt(9.0);System.out.println(sqrt);//3.0//7.random 求随机数//  random 返回的是 0 <= x < 1 之间的一个随机小数// 思考:请写出获取 a-b之间的一个随机整数,a,b均为整数 ,比如 a = 2, b=7//  即返回一个数 x  2 <= x <= 7// 老韩解读 Math.random() * (b-a) 返回的就是 0  <= 数 < b-a// (1) (int)(a) <= x <= (int)(a + Math.random() * (b-a +1) )// (2) 使用具体的数给小伙伴介绍 a = 2  b = 7//  (int)(a + Math.random() * (b-a +1) ) = (int)( 2 + Math.random()*6)//  Math.random()*6 返回的是 0 <= x < 6 小数//  2 + Math.random()*6 返回的就是 2<= x < 8 小数//  (int)(2 + Math.random()*6) = 2 <= x <= 7// (3) 公式就是  (int)(a + Math.random() * (b-a +1) )for(int i = 0; i < 100; i++) {System.out.println((int)(2 +  Math.random() * (7 - 2 + 1)));}//max , min 返回最大值和最小值int min = Math.min(1, 9);int max = Math.max(45, 90);System.out.println("min=" + min);System.out.println("max=" + max);}
}

Arrays类

  • Arrays类常见方法应用案例
    ArraysMethod01.java
    Arrays里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)
    1)toString 返回数组的字符串形式
    Arrays.toString(arr)
    2)sort排序(自然排序和定制排序)
    ArraysSortCustom.java
    ArraysMethod02.java
    3)binarySearch 通过二分搜索法进行查找,要求必须排好序
    int index = Arrays.binarySearch(arr, 3);
    4)copyOf数字元素的复制
    Integer[] newArr = Arrays.copyOf(arr, arr.length);
    5)fill数组元素的填充
    Integer[] num = new Integer[]{9,3,2};
    Arrays.fill(num, 99)
    6)equals比较两个数组元素内容是否完全一致
    boolean equals = Arrays.equals(arr, arr2);
    7)asList将一组值,转换成list
    List asList = Arrays.asList(2,3,4,5,6,1);
    System.out.println(“asList=” + asList);

实例实现:
ArraysMethod01.java

import java.util.Arrays;
import java.util.Comparator;public class ArraysMethod01 {public static void main(String[] args) {Integer[] integers = {1, 20, 90};//遍历数组
//        for(int i = 0; i < integers.length; i++){//            System.out.println(integers[i]);
//        }//直接使用Arrays.toString方法,显示数组System.out.println(Arrays.toString(integers));  //[1, 20, 90]//演示sort方法的使用Integer arr[] = {1, -1, 7, 0, 89};//进行排序//老韩解读//1.可以直接使用冒泡排序,也可以直接使用Arrays提供的sort方法排序//2.因为数组是引用类型,所以通过sort排序后,会直接影响到实参arr//3. sort重载的,也可以通过传入一个接口Comparator 实现定制排序//4.调用定制排序时,传入两个参数(1) 排序的数组arr//(2) 实现了Comparator接口的匿名内部类,要求实现compara方法//5. 先演示效果,在解释//6. 这里体现了接口编程的方式, 看看源码,就明白了// 源码分析//(1) Arrays.sort(arr, new Comparator()//(2) 最终到 TimSort类的 private static <T> void binarySort(T[] a, int lo, int hi, int start,//                                       Comparator<? super T> c)//(3) 执行到 binarySort方法的代码, 会根据动态绑定机制 c.compare()执行我们传入的//      匿名内部类的  compare ()//      while (left < right) {//                int mid = (left + right) >>> 1;//                if (c.compare(pivot, a[mid]) < 0)//                    right = mid;//                else//                    left = mid + 1;//            }//(4) new Comparator() {//            @Override//            public int compare(Object o1, Object o2) {//                Integer i1 = (Integer) o1;//                Integer i2 = (Integer) o2;//                return i2 - i1;//            }//        }//(5)  public int compare(Object o1, Object o2) 返回的值>0还是<0//      会影响整个排序结果, 这就充分体现了 接口编程+动态绑定+匿名内部类的综合使用//      将来的底层框架和源码的使用方式,会非常常见//Arrays.sort(arr);     //默认排序方法//定制排序Arrays.sort(arr, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {Integer i1 = (Integer) o1;Integer i2 = (Integer) o2;return i2 - i1;}});System.out.println("===排序后===");System.out.println(Arrays.toString(arr));   //[-1, 0, 1, 7, 89]}
}

ArraysSortCustom.java

import java.util.Arrays;
import java.util.Comparator;public class ArraysSortCustom {public static void main(String[] args) {int[] arr = {1, -1, 8, 0, 20};//bubble01(arr);bubble02(arr, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {int i1 = (Integer) o1;int i2 = (Integer) o2;return i1 - i2;     //return i2 - i1;}});System.out.println("==定制排序后的情况==");System.out.println(Arrays.toString(arr));}//使用冒泡完成排序public static void bubble01(int[] arr) {int temp = 0;for(int i = 0; i < arr.length -1; i++){for(int j = 0; j < arr.length - 1 - i; j++){//从小到大if(arr[j] > arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}//结合冒泡 + 定制public static void bubble02(int[] arr, Comparator c){int temp = 0;for(int i = 0; i < arr.length - 1; i++){for(int j = 0; j < arr.length - 1 - i; j++){//数组排序由 c.compare(arr[j], arr[j + 1])返回的值决定if(c.compare(arr[j], arr[j + 1]) > 0){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}
}

ArraysMethod02.java

import java.util.Arrays;
import java.util.List;public class ArraysMethod02 {public static void main(String[] args) {Integer[] arr = {1, 2, 90, 123, 567};//binarySearch 通过二分搜索法进行查找,要求必须排好序//老韩解读//1.使用 binarySearch 二叉查找//2. 要求该数组是有序的, 如果该数组是无序的, 不能使用binarySearch//3. 如果数组中不存在该元素,就返回  return -(low + 1);  // key not found.//      其中low为元素应该存在的位置, 例如568应在567之后, 则low应为5int index = Arrays.binarySearch(arr, 568);System.out.println("index=" + index);   //index=-6//copyOf数字元素的复制//老韩解读//1. 从arr数组中, 拷贝arr.length个元素到 newArr数组中//2. 如果拷贝的长度 > arr.length 就在新数组的后面 增加null//3. 如果拷贝长度 < 0 就抛出异常NegativeArraySizeException//4. 该方法的底层使用的是 System.arraycopy()Integer[] newArr = Arrays.copyOf(arr, arr.length - 1);System.out.println("===拷贝执行完毕后==");System.out.println(Arrays.toString(newArr));    //[1, 2, 90, 123]//ill 数组元素的填充Integer[] num = new Integer[]{9, 3, 2};//老韩解读//1. 使用99 去填充 num数组, 可以理解是替换原来的元素Arrays.fill(num, 99);System.out.println(Arrays.toString(num));   //[99, 99, 99]//equals比较两个数组元素内容是否完全一致Integer[] arr2 = {1, 2, 90, 123};//老韩解读//1. 如果arr 和 arr2 数组的元素一样,则方法true//2. 如果不是完全一样,就返回falseboolean equals = Arrays.equals(arr, arr2);System.out.println("equals=" + equals);     //equals=false//asList将一组值,转换成list//老韩解读//1. asList方法, 会将(2,3,4,5,6,1)数据转成一个List集合//2. 返回的 asList 编译类型 List(接口)//3. asList 运行类型 java.util.Arrays$ArrayList, 是Arrays类的//      静态内部类 private static class ArrayList<E> extends AbstractList<E>//        implements RandomAccess, java.io.SerializableList asList = Arrays.asList(2,3,4,5,6,1);System.out.println("asList=" + asList.getClass());}
}

System类

  • System类常见方法和案例
    1)exit退出当前程序
    2)arraycopy:复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组
int[] src = {1,2,3};
int[] dest = new int[3];
System.arraycopy(src, 0, dest, 0, 3);

3)currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
4)gc:运行垃圾回收机制System.gc();

BigInteger和BigDecimal类

  • BigInteger和BigDecimal介绍
    应用场景:
    1)BigInteger适合保存比较大的整型
    2)BigDecimal适合保存精读更高的浮点型(小数)

  • BigInteger和BidDecimal常见方法
    1)add加
    2)substract减
    3)multiply乘
    4)divide除

日期类

第一代日期类

1)Date:精确到毫秒,代表特定的瞬间
2)SimpleDateFormat:格式和解析日期的类
SimpleDateFormat格式化和解析日期的具体类。它允许进行格式化(日期->文本)、解析(文本->日期)和规范化


案例使用:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class Date01 {public static void main(String[] args) throws ParseException {//老韩解读//1. 获取当前系统时间//2. 这里的Date 类是在java.util包//3. 默认输出的日期格式是国外的方式, 因此通常需要对格式进行转换Date d1 = new Date(); //获取当前系统时间System.out.println("当前日期=" + d1);Date d2 = new Date(9234567); //通过指定毫秒数得到时间System.out.println("d2=" + d2); //获取某个时间对应的毫秒数
////老韩解读//1. 创建 SimpleDateFormat对象,可以指定相应的格式//2. 这里的格式使用的字母是规定好,不能乱写SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");String format = sdf.format(d1); // format:将日期转换成指定格式的字符串System.out.println("当前日期=" + format);//老韩解读//1. 可以把一个格式化的String 转成对应的 Date//2. 得到Date 仍然在输出时,还是按照国外的形式,如果希望指定格式输出,需要转换//3. 在把String -> Date , 使用的 sdf 格式需要和你给的String的格式一样,否则会抛出转换异常String s = "1996年01月01日 10:20:30 星期一";Date parse = sdf.parse(s);System.out.println("parse=" + sdf.format(parse));}
}

第二代日期类

1)第二代日期类,主要就是Calender类(日历)
public abstract class Calendar extends Object implements Serializable, Cloneable, Comparable
2)Calendar类是一个抽象类,它为特定瞬间与一组诸如YEAr、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。


import java.util.Calendar;public class Calendar_ {public static void main(String[] args) {//老韩解读//1. Calendar是一个抽象类,并且构造器是private//2. 可以通过getInstance() 来获取实例//3. 提供大量的方法和字段提供给程序员//4. Calendar没有提供对应的格式化的类,因此需要程序员自己组合来输出(灵活)//5. 如果我们需要按照24小时进制来获取时间, Calendar.HOUR ==改成=> Calendar.HOUR_OF_DAY//CalendarCalendar c = Calendar.getInstance(); //创建日历类对象//比较简单,自由System.out.println("c=" + c);//2.获取日历对象的某个日历字段System.out.println("年:" + c.get(Calendar.YEAR));// 这里为什么要 + 1, 因为Calendar 返回月的时候,是按照 0 开始编号System.out.println("月:" + (c.get(Calendar.MONTH) + 1));System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));System.out.println("小时:" + c.get(Calendar.HOUR));System.out.println("分钟:" + c.get(Calendar.MINUTE));System.out.println("秒:" + c.get(Calendar.SECOND));//Calender 没有专门的格式化方法,所以需要程序员自己来组合显示System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" + c.get(Calendar.DAY_OF_MONTH) +" " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) );}
}

第三代日期类

  • 前面两代日期类的不足分析
    JDK1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK1.1引入Calendar类之后被弃用了。而Calendar也存在问题是:
    1)可变性:像日期和时间这样的类应该是不可变的。
    2)偏移性:Date中的年份是从1900开始的,而月份都从0开始。
    3)格式性:格式化只对Date有用,Calendar则不行。
    4)此外,它们也不是线程安全的;不能处理闰秒等(每隔2天,多出1s)。

  • 第三代日期类常见方法

1)LocalDate(日期/年月日)、LocalTime(时间/时分秒)、LocalDateTime(日期时间/年月日时分秒)JDK8加入

LocalDate只包含日期,可以获取日期字段
LocalTime只包含时间,可以获取时间字段
LocalDateTime 包含日期+时间,可以获取日期和时间字段

  • DateTimeFormatter格式日期类
    类似于SimpleDateFormat

DateTimeFormat dtf = DateTimeFormatter.ofPattern(格式);
String str = dtf.format(日期对象);

使用案例:


import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;public class LocalDate_ {public static void main(String[] args) {//第三代日期//老韩解读//1. 使用now() 返回表示当前日期时间的 对象LocalDateTime ldt = LocalDateTime.now(); //LocalDate.now();//LocalTime.now()System.out.println(ldt);//2. 使用DateTimeFormatter 对象来进行格式化// 创建 DateTimeFormatter对象DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String format = dateTimeFormatter.format(ldt);System.out.println("格式化的日期=" + format);System.out.println("年=" + ldt.getYear());System.out.println("月=" + ldt.getMonth());System.out.println("月=" + ldt.getMonthValue());System.out.println("日=" + ldt.getDayOfMonth());System.out.println("时=" + ldt.getHour());System.out.println("分=" + ldt.getMinute());System.out.println("秒=" + ldt.getSecond());LocalDate now = LocalDate.now(); //可以获取年月日LocalTime now2 = LocalTime.now();//获取到时分秒//提供 plus 和 minus方法可以对当前时间进行加或者减//看看890天后,是什么时候 把 年月日-时分秒LocalDateTime localDateTime = ldt.plusDays(890);System.out.println("890天后=" + dateTimeFormatter.format(localDateTime));//看看在 3456分钟前是什么时候,把 年月日-时分秒输出LocalDateTime localDateTime2 = ldt.minusMinutes(3456);System.out.println("3456分钟前 日期=" + dateTimeFormatter.format(localDateTime2));}
}
  • Instant 时间戳
    类似于Date
    提供了一系列和Date类转换的方式
    Instant–> Date:
    Date date = Date.from(instant);
    Date–>Instant:
    Instant instant = date.toInstant();

使用案例:


import java.time.Instant;
import java.util.Date;public class Instant_ {public static void main(String[] args) {//1.通过 静态方法 now() 获取表示当前时间戳的对象Instant now = Instant.now();System.out.println(now);//2. 通过 from 可以把 Instant转成 DateDate date = Date.from(now);//3. 通过 date的toInstant() 可以把 date 转成Instant对象Instant instant = date.toInstant();}
}
  • 第三代日期类更多方法
    LocalDateTime类
    MonthDay类:检查重复事件
    是否是闰年
    增加日期的某个部分
    使用plus方法测试增加时间的某个部分
    使用minus方法测试查看一年前和一年后的日期

章节作业

作业1:
(1) 将字符串中指定部分进行反转。比如将"abcdef"反转为"aedcbf"
(2) 编写方法 public static String reverse(String str, int start , int end)

package com.hspedu.homework;public class Homework01 {public static void main(String[] args) {//测试String str = "abcdef";System.out.println("===交换前===");System.out.println(str);try {str = reverse(null, 1, 4);} catch (Exception e) {System.out.println(e.getMessage());return;}System.out.println("===交换后===");System.out.println(str);}/*** (1) 将字符串中指定部分进行反转。比如将"abcdef"反转为"aedcbf"* (2) 编写方法 public static String reverse(String  str, int start , int end) 搞定* 思路分析* (1) 先把方法定义确定* (2) 把 String 转成 char[] ,因为char[] 的元素是可以交换的* (3) 画出分析示意图* (4) 代码实现*/public static String reverse(String str, int start, int end){//对输入的参数做一个验证//重要的编程技巧!!!//(1) 写出正确的情况//(2) 然后取反if(!(str != null && start >= 0 && end > start && end < str.length())){throw new RuntimeException("参数不正确");}char[] chars = str.toCharArray();char temp = ' ';    //交换辅助变量for(int i = start, j = end; i < j; i++, j--){temp = chars[i];chars[i] = chars[j];chars[j] = temp;}//使用chars重新构建一个String 返回即可return new String(chars);}
}

作业2:
输入用户名、密码、邮箱,如果信息录入正确,则提示注册成功,否则生成异常对象
要求:
(1) 用户名长度为2或3或4
(2) 密码的长度为6,要求全是数字 isDigital
(3) 邮箱中包含@和. 并且@在.的前面

package com.hspedu.homework;public class Homework02 {public static void main(String[] args) {String name = "jack";String pwd = "123456";String email = "jack@sohu.com";try{userRegister(name, pwd, email);System.out.println("恭喜你,注册成功~");}catch(Exception e){System.out.println(e.getMessage());}}/*** 输入用户名、密码、邮箱,如果信息录入正确,则提示注册成功,否则生成异常对象* 要求:* (1) 用户名长度为2或3或4* (2) 密码的长度为6,要求全是数字  isDigital* (3) 邮箱中包含@和.   并且@在.的前面* <p>* 思路分析* (1) 先编写方法 userRegister(String name, String pwd, String email) {}* (2) 针对输入的内容进行校验, 如果发现有问题, 就抛出异常,给出提示* (3) 单独的写一个方法,判断密码是否全部是数字字符boolean*/public static void userRegister(String name, String pwd, String email) {//再加入一些校验if(!(name != null && pwd != null && email != null)){throw new RuntimeException("参数不能为null");}//过关//第一关int userLength = name.length();if (!(userLength >= 2 && userLength <= 4)) {throw new RuntimeException("用户名长度为2或3或4");}//第二关if (!(pwd.length() == 6 && isDigital(pwd))) {throw new RuntimeException("密码的长度为6,要求全是数字");}//第三关int i = email.indexOf('@');int j = email.indexOf('.');if (!(i > 0 && j > i)) {throw new RuntimeException("邮箱中包含@和.   并且@在.的前面");}}//单独的写一个方法,判断密码是否全部是数字字符booleanpublic static boolean isDigital(String str) {char[] chars = str.toCharArray();for (int i = 0; i < chars.length; i++) {if (chars[i] < '0' || chars[i] > '9') {return false;}}return true;}
}

作业3:
编写方法: 完成输出格式要求的字符串
编写java程序,输入形式为: Han shun Ping的人名,以Ping,Han .S的形式打印出来 。其中.S是中间单词的首字母

package com.hspedu.homework;public class Homework03 {public static void main(String[] args) {String name = "Willian Jefferson Clinton";printName(name);}/*** 编写方法: 完成输出格式要求的字符串* 编写java程序,输入形式为: Han shun Ping的人名,以Ping,Han .S的形式打印*       出来    。其中.S是中间单词的首字母* 思路分析* (1) 对输入的字符串进行 分割split(" ")* (2) 对得到的String[] 进行格式化String.format()* (3) 对输入的字符串进行校验即可*/public static void printName(String str){if(str == null){System.out.println("str 不能为空");return;}String[] names = str.split(" ");if(names.length != 3){System.out.println("输入的字符串格式不对");return;}String format = String.format("%s,%s .%c", names[2], names[0], names[1].toUpperCase().charAt(0));System.out.println(format);}
}

作业4:

package com.hspedu.homework;public class Homework05 {public static void main(String[] args) {String s1 = "hspedu";Animal a = new Animal(s1);Animal b = new Animal(s1);System.out.println(a == b);     //fSystem.out.println(a.equals(b));     //fSystem.out.println(a.name == b.name);   //tString s4 = new String("hspedu");String s5 = "hspedu";System.out.println(s1 == s4);   //fSystem.out.println(s4 == s5);   //fString t1 = "hello" + s1;String t2 = "hellohspedu";System.out.println(t1.intern() == t2);  //t}
}class Animal {String name;public Animal(String name) {this.name = name;}
}

第14章 集合

集合的理解和好处

  • 数组
    1)长度开始时必须制定,而且一旦制定,不能更改
    2)保存的必须为同一类型的元素
    3)使用数组进行增加/删除元素的示意代码 - 比较麻烦

  • 集合
    1)可以动态保存任意多个对象,使用比较方便!
    2)提供了一系列方便的操作对象的方法:add、remove、set、get等
    3)使用集合添加,删除新元素的示意代码- 简洁了

集合的框架体系

Java的集合类很多,主要分为两大类,如图:

Collection接口和常用方法

  • Collection接口实现类特点
    public interface Collectionextends Iterable
    1)collection实现子类可以存放多个元素,每个元素可以是Object
    2)有些Collection的实现类,可以存放重复的元素,有些不可以
    3)有些Collection的实现类,有些是有序的(List), 有些不是有序(Set)
    4)Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

Collection接口常用方法,以实现子类ArrayList来演示
1)add:添加单个元素
2)remove:删除指定元素
3)contains:查找元素是否存在
4)size:获取元素个数
5)isEmpty:判断是否为空
6)clear:清空
7)addAll:添加多个元素
8)containAll:查找多个元素是否都存在
9)removeAll:删除多个元素
10)说明:以ArrayList实现类来演示

import java.util.ArrayList;
import java.util.List;public class CollectionMethod {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();
//        add:添加单个元素list.add("jack");list.add(10);   //list.add(new Integer(10))list.add(true);System.out.println("list=" + list);
//        remove:删除指定元素//list.remove(0); //删除第一个元素list.remove(true);  //指定删除某个元素System.out.println("list=" + list);
//        contains:查找元素是否存在System.out.println(list.contains("jack"));  //T
//        size:获取元素个数System.out.println(list.size());    //2
//        isEmpty:判断是否为空System.out.println(list.isEmpty());     //F
//        clear:清空list.clear();System.out.println("list=" + list);
//        addAll:添加多个元素ArrayList list2 = new ArrayList();list2.add("红楼梦");list2.add("三国演义");list.addAll(list2);System.out.println("list=" + list);
//        containAll:查找多个元素是否都存在System.out.println(list.containsAll(list2));    //T
//        removeAll:删除多个元素list.add("聊斋");list.removeAll(list2);System.out.println("list=" + list);}
}
  • Collection接口遍历元素方式 1-使用Iterator(迭代器)
    √基本介绍

    1)Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
    2)所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器
    3)Iterator的结构[看一张图]
    4)Iterator仅用于遍历集合,Iterator本身并不存放对象

案例:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class CollectionIterator {@SuppressWarnings({"all"})public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book("三国演义", "罗贯中", 10.1));col.add(new Book("小李飞刀", "古龙", 5.1));col.add(new Book("红楼梦", "曹雪芹", 34.6));//System.out.println("col=" + col);//现在老师希望能够遍历col集合//1.先得到 col 对应的迭代器Iterator iterator = col.iterator();//2.使用while循环遍历while(iterator.hasNext()){  //判断是否还有数据//返回下一个元素,类型是ObjectObject obj = iterator.next();System.out.println("obj=" + obj);}//一个快捷键,快速生成while(iterator.hasNext()) => itit//显示所有的快捷键的快捷键 ctrl + j//3. 当退出while循环后,这时iterator迭代器,指向最后的元素//iterator.next();    //NoSuchElementException//4. 如果希望再次遍历,需要重置我们的迭代器iterator = col.iterator();System.out.println("===第二次遍历===");while(iterator.hasNext()){Object obj = iterator.next();System.out.println("obj=" + obj);}}
}class Book{private String name;private String author;private double price;public Book(String name, String author, double price) {this.name = name;this.author = author;this.price = price;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +'}';}
}
  • Collection接口遍历对象方式2- for循环增强
    增强for循环,可以替代iterator迭代器,特点:增强for就是简化版的iterator,本质一样。只能用于遍历集合或数组。

√基本数组
for(元素类型 元素名: 集合名或数组名){
访问元素
}

案例:

package com.hspedu.collection_;import java.util.ArrayList;
import java.util.Collection;public class CollectionFor {@SuppressWarnings("all")public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book("三国演义", "罗贯中", 10.1));col.add(new Book("小李飞刀", "古龙", 5.1));col.add(new Book("红楼梦", "曹雪芹", 34.6));//老韩解读//1. 使用增强for, 在Collection集合//2. 增强for, 底层仍然是迭代器//3. 增强for可以理解成就是简化版本的 迭代器遍历//4. 快捷键方式Ifor(Object book : col){System.out.println("book=" + book);}//增强for,也可以直接在数组使用int[] nums =  {1, 8, 10, 90};for(int i : nums){System.out.println("i=" + i);}}
}

List接口和常用方法

  • List接口基本介绍
    List接口是Collection接口的子接口
  1. List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
  2. List集合中的每个元素都有其对应的顺序索引,即支持索引。
  3. List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
  4. JDK API 中list接口的实现类有:
  • List接口的常用方法

实例演示:

package com.hspedu.list_;import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;public class ListMethod {@SuppressWarnings({"all"})public static void main(String[] args) {List list = new ArrayList();list.add("张三丰");list.add("贾宝玉");
//      void add(int index, Object ele): 在index位置插入ele元素//在index = 1的位置插入一个对象list.add(1,"韩顺平");System.out.println("list=" + list);
//      boolean addAll(int index, Collection eles): 从index位置开始将eles中的所有元素添加进来List list2 = new ArrayList();list2.add("jack");list2.add("tom");list.addAll(1, list2);System.out.println("list=" + list);//      Object get(int index): 获取指定index位置的元素//说过
//      int indexOf(Object obj): 返回obj在集合中首次出现的位置System.out.println(list.indexOf("tom"));    //2
//      int lastIndexOf(Object obj): 返回obj在当前集合中末次出现的位置list.add("韩顺平");System.out.println("list=" + list);System.out.println(list.lastIndexOf("韩顺平"));
//      Object remove(int index):移除指定index位置的元素,并返回此元素list.remove(0);System.out.println("list=" + list);
//      Object set(int index, Object ele):设置指定index位置的元素为ele,相当于是替换list.set(1, "玛丽");System.out.println("list=" + list);
//      List subList(int fromIndex, int toIndex): 返回从fromIndex到toIndex位置的子集合//注意返回的子集合 fromIndex <= subList < toIndexList returnlist = list.subList(0, 2);System.out.println("returnlist=" + returnlist);}
}
  • List的三种遍历方式[ArrayList, LinkedList, Vector]

ArrayList底层结构和源码分析

  • ArrayList的注意事项
  1. permits all elements, including null, ArrayList可以加入null,并且多个
  2. ArrayList是由数组来实现数据存储的
  3. ArrayList基本等同与Vector,除了ArrayList是线程不安全(执行效率高)看源码。在多线程情况下,不建议使用ArrayList
  • ArrayList的底层操作机制源码分析(重点,难点)

Vector底层结构和源码剖析

  • Vector的基本介绍
  • Vector和ArrayList的比较

LinkedList底层结构

  • LinkedList的全面说明
  1. LinkedList底层实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,没有实现同步
  • LinkedList的底层操作机制
  • LinkedList的增删改查案例
package com.hspedu.list_;import java.util.Iterator;
import java.util.LinkedList;@SuppressWarnings({"all"})
public class LinkedListCRUD {public static void main(String[] args) {LinkedList linkedList = new LinkedList();linkedList.add(1);linkedList.add(2);linkedList.add(3);System.out.println("linkedList=" + linkedList);//演示一个删除结点的linkedList.remove();    //这里默认删除的是第一个结点//linkedList.remove(2);System.out.println("linkedList=" + linkedList);//修改某个结点对象linkedList.set(1, 999);System.out.println("linkedList=" + linkedList);//得到某个结点对象//get(1)是得到双向链表的第二个对象Object o = linkedList.get(1);System.out.println(o);  //999//因为LinkedList是实现了List接口, 遍历方式System.out.println("===LinkedList遍历迭代器====");Iterator iterator = linkedList.iterator();while (iterator.hasNext()) {Object next =  iterator.next();System.out.println("next=" + next);}System.out.println("===LinkedList遍历增强for====");for (Object o1 :linkedList) {System.out.println("o1=" + o1);}System.out.println("===LinkedList遍历普通for====");for (int i = 0; i < linkedList.size(); i++) {System.out.println(linkedList.get(i));}//源码阅读/* 1. LinkedList linkedList = new LinkedList();public LinkedList() {}2. 这时 linkedList的属性 first = null    last = null3. 执行 添加public boolean add(E e) {linkLast(e);return true;}4. 将新的结点,加入到双向链表的最后void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;}*//*读源码 linkedList.remove();    //这里默认删除的是第一个结点1.执行public E remove() {return removeFirst();}2.执行public E removeFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return unlinkFirst(f);}3.执行 unlinkFirst,将f 指向的双向链表的第一个结点删除private E unlinkFirst(Node<E> f) {// assert f == first && f != null;final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next;if (next == null)last = null;elsenext.prev = null;size--;modCount++;return element;}*/}}
  • ArrayList 和LinkedList比较

Set接口和常见方法

  • Set接口基本介绍

  • Set接口的常用方法
    和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样

  • Set接口的遍历方式
    同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。
    1.可以使用迭代器
    2.增强for
    3.不能使用索引的方式来获取

  • Set接口的常用方法举例

package com.hspedu.set_;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;@SuppressWarnings({"all"})
public class SetMethod {public static void main(String[] args) {//老韩解读//1. 以Set接口的实现类 HashSet来讲解Set接口的方法//2. set 接口的实现类的对象(Set接口对象), 不能存放重复的元素,可以添加一个null//3. set接口对象存放数据是无序(即添加的顺序和取出的顺序不一致)//4. 注意:取出的顺序虽然不是添加的顺序,但是它是固定的Set set = new HashSet();set.add("john");set.add("lucy");set.add("john");    //重复set.add("jack");set.add("hsp");set.add("mary");set.add(null);//set.add(null);      //再次添加nullfor (int i = 0; i < 10; i++) {System.out.println("set=" + set);}//遍历//方式1:  使用迭代器System.out.println("===使用迭代器===");Iterator iterator = set.iterator();while(iterator.hasNext()){Object obj= iterator.next();System.out.println("obj=" + obj);}set.remove(null);//方式2: 增强forSystem.out.println("===增强for====");for(Object o : set){System.out.println("o=" + o);}//set接口对象, 不能通过索引来获取}
}

Set接口实现类-HashSet

  • HashSet的全面说明
  • HashSet案例说明(两个案例)
package com.hspedu.set_;import java.util.HashSet;@SuppressWarnings({"all"})
public class HashSet01 {public static void main(String[] args) {HashSet set = new HashSet();//说明//1. 在执行add方法后,会返回一个boolean值//2. 如果添加成功, 返回 true , 否则返回false//3. 可以通过 remove 指定删除哪个对象System.out.println(set.add("john"));    //TSystem.out.println(set.add("lucy"));    //TSystem.out.println(set.add("john"));    //FSystem.out.println(set.add("jack"));    //TSystem.out.println(set.add("Rose"));    //Tset.remove("john");System.out.println("set=" + set);   //3个//set = new HashSet();System.out.println("set=" + set);   //0个//4 Hashset 不能添加相同的元素/数据?set.add("lucy");    //添加成功set.add("lucy");    //加入不了set.add(new Dog("tom"));    //okset.add(new Dog("tom"));    //okSystem.out.println("set=" + set);//在加深一下,非常经典的面试题//看源码, 做分析, 先给小伙伴留一个坑, 以后讲完源码, 就了然//去看它的源码,即 add 到底发生了什么? => 底层机制set.add(new String("hsp")); //okset.add(new String("hsp")); //加入不了System.out.println("set=" + set);}
}class Dog{private String name;public Dog(String name) {this.name = name;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +'}';}
}
  • HashSet底层机制说明(大量源码,有点难度,多理解)
package com.hspedu.set_;import java.util.HashSet;@SuppressWarnings({"all"})
public class HashSetSource {public static void main(String[] args) {HashSet hashSet = new HashSet();hashSet.add("java");    //到此位置,第1次add分析完毕。hashSet.add("php");     //到此位置,第2次add分析完毕hashSet.add("java");System.out.println("set=" + hashSet);/*老韩对HashSet 的源码解读1.执行HashSet()public HashSet() {map = new HashMap<>();}2.执行add()public boolean add(E e) {   //e = "java"return map.put(e, PRESENT)==null;   //(static) PRESENT = new Object();}3.执行put() , 该方法会执行 hash(key) 得到key对应的hash值 算法 h = key.hashCode()) ^ (h >>> 16)public V put(K key, V value) {  //key = "java"  value = PRESENT 共享return putVal(hash(key), key, value, false, true);}4.执行 putValfinal V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;     //定义了辅助变量//table 就是 Hashtable 的一个数组, 类型是 Node[]//if 语句表示如果当前table 是 null, 或者 大小 = 0//就是第一次扩容, 到16个空间if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//(1)根据key, 得到hash去计算该key应该存放到table表的哪个索引位置//并把这个位置的对象,赋给p//(2)判断p是否为null//(2.1) 如果p为null, 表示还没有存放元素, 就创建一个Node(key = "java", value = PRESENT)//(2.2) 就放在该位置 tab[i] = newNode(hash, key, value, null);if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {//一个开发技巧提示: 在需要局部变量(辅助变量)时候, 在创建Node<K,V> e; K k;//如果当前索引位置对应的链表的第一个元素和准备添加的key的hash值一样//并且满足 下面两个条件之一://(1) 准备加入的key 和 p指向的Node 结点的key是同一对象//(2) p指向的Node 结点的key的equals() 和准备加入的key比较后相同//就不能加入if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//再判断p是不是一棵红黑树,//如果是一棵红黑树,就调用putTreeVal,来进行添加else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {  //如果table对应索引位置, 已经是一个链表, 就使用for循环比较//(1) 依次和该链表的每一个元素比较后, 都不相同, 则加入到该链表的最后//    注意在把元素添加到链表后,立即判断 该链表是否达到8个结点//    ,就调用 treeifyBin() 对当前这个链表进行树化(转成红黑树)//    注意,在转成红黑树时,要进行判断, 判断条件//    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY(64))//            resize();//    如果上面条件成立, 先table扩容,//    只有上面条件不成立时, 才进行转成红黑树//(2) 依次和该链表的每个元素比较过程中,如果有相同情况, 就直接breakfor (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}*/}
}

Set接口实现类-LinkedHashSet

  • LinkedHashSet的全面说明
  • 案例演示
package com.hspedu.set_;import java.util.LinkedHashSet;
import java.util.Objects;@SuppressWarnings({"all"})
public class LinkedHashSetExercise {public static void main(String[] args) {LinkedHashSet linkedHashSet = new LinkedHashSet();linkedHashSet.add(new Car("奥拓", 1000));     //OKlinkedHashSet.add(new Car("奥迪", 300000));   //OKlinkedHashSet.add(new Car("法拉利", 10000000));  //OKlinkedHashSet.add(new Car("奥迪", 300000));   //加入不了linkedHashSet.add(new Car("保时捷", 70000000));    //OKlinkedHashSet.add(new Car("奥迪", 300000));   //加入不了System.out.println("linkedHashSet=" + linkedHashSet);}
}/*** Car 类(属性:name,price),  如果 name 和 price 一样,* 则认为是相同元素,就不能添加。 5min*/class Car {private String name;private double price;public Car(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "\nCar{" +"name='" + name + '\'' +", price=" + price +'}';}//重写equals方法和hashCode//当name 和 price 相同时, 就返回相同的 hashCode 值, equals返回@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Car car = (Car) o;return Double.compare(car.price, price) == 0 &&Objects.equals(name, car.name);}@Overridepublic int hashCode() {return Objects.hash(name, price);}
}

Map接口的常用方法

  • Map接口实现类的特点【很实用】

    特点案例:
package map_;import java.util.HashMap;
import java.util.Map;@SuppressWarnings({"all"})
public class Map_ {public static void main(String[] args) {//老韩解读Map接口实现类的特点, 使用实现类HashMap//1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)//2. Map 中的 key 和 value 可以是任何引用类型的数据, 会封装到HashMap$Node 对象中//3. Map 中的 hey 不允许重复, 原因和HashSet一样, 前面分析过源码//4. Map 中的 value 可以重复//5. Map 的 key可以为 null, value 也可以为 null , 注意key为null, 只能有一个, value为null, 可以多个//6. 常用String类作为Map的 key//7. key 和 value 之间存在单向一对一关系, 即通过指定的key总能找到对应的valueMap map = new HashMap();map.put("no1", "韩顺平");  //k-vmap.put("no2", "张无忌");  //k-vmap.put("no1", "张三丰");  //当有相同的k ,就等价与替换map.put("no3", "张三丰");  //k-vmap.put(null, null);    //k-vmap.put(null, "abc");   //等价替换map.put("no4", null);   //k-vmap.put("no5", null);   //k-vmap.put(1, "赵敏");   //k-vmap.put(new Object(), "金毛狮王");  //k-v//通过get方法, 传入key, 会返回对应的valueSystem.out.println(map.get("no2"));     //张无忌System.out.println("map=" + map);}
}

  • Map接口常用方法

演示案例:

package map_;import java.util.HashMap;
import java.util.Map;@SuppressWarnings({"all"})
public class MapMethod {public static void main(String[] args) {//演示map接口常见方法Map map = new HashMap();map.put("邓超", new Book("", 100));//OKmap.put("邓超", "孙俪");//替换-> 一会分析源码map.put("王宝强", "马蓉");//OKmap.put("宋喆", "马蓉");//OKmap.put("刘令博", null);//OKmap.put(null, "刘亦菲");//OKmap.put("鹿晗", "关晓彤");//OKmap.put("hsp", "hsp的老婆");System.out.println("map=" + map);//        remove:根据键删除映射关系map.remove(null);System.out.println("map=" + map);
//        get:根据键获取值Object val = map.get("鹿晗");System.out.println("val=" + val);
//        size:获取元素个数System.out.println("k-v=" + map.size());
//        isEmpty:判断个数是否为0System.out.println(map.isEmpty());  //F
//        clear:清除k-v//map.clear();System.out.println("map=" + map);//        containsKey:查找键是否存在System.out.println(map.containsKey("hsp")); //T}
}class Book{private String name;private int num;public Book(String name, int num) {this.name = name;this.num = num;}
}
  • Map接口遍历方法


使用函数:

  1. containsKey:查找键是否存在
  2. keySet: 获取所有的键
  3. entrySet: 获取所有关系k-v
  4. values: 获取所有的值

案例演示:

package map_;import java.util.*;@SuppressWarnings({"all"})
public class MapFor {public static void main(String[] args) {Map map = new HashMap();map.put("邓超", "孙俪");map.put("王宝强", "马蓉");map.put("宋喆", "马蓉");map.put("刘令博", null);map.put(null, "刘亦菲");map.put("鹿晗", "关晓彤");//第一组: 先取出 所有的Key , 通过Key 取出对应的ValueSet keyset = map.keySet();//(1) 增强forSystem.out.println("-----第一种方式------");for (Object key :keyset) {System.out.println(key + "-" + map.get(key));}//(2) 迭代器System.out.println("----第二种方式----");Iterator iterator = keyset.iterator();while(iterator.hasNext()){Object key = iterator.next();System.out.println(key + "-" + map.get(key));}//第二组: 把所有的values取出Collection values = map.values();//这里可以使用所有的Collections使用的遍历方法//(1) 增强forSystem.out.println("---取出所有的value 增强for---");for(Object value : values){System.out.println(value);}//(2)迭代器System.out.println("---取出所有的value 迭代器---");Iterator iterator2 = values.iterator();while(iterator2.hasNext()){Object value = iterator2.next();System.out.println(value);}//第三组: 通过EntrySet来获取 k-vSet entrySet = map.entrySet();  // EntrySet<Map.Entry<K,V>>//(1) 增强forSystem.out.println("----使用EntrySet 的 for 增强(第3种)----");for(Object entry : entrySet){//将entry 转成 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}//(2)迭代器System.out.println("---使用EntrySet 的 迭代器(第4种)----");Iterator iterator3 = entrySet.iterator();while (iterator3.hasNext()) {Object entry =  iterator3.next();//System.out.println(next.getClass());    //HashMap$Node -实现 -> Map.Entry(getKey,getValue)//向下转型 Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}}
}

Map接口实现类- HashMap

  • HashMap小结
  • HashMap底层机制及源码剖析

Map接口实现类- Hashable

  • HashTable的基本介绍
  • Hashable和HashMap对比

Map接口实现类-Properties

  • 基本介绍
  • 基本使用

案例:

package map_;import java.util.Properties;@SuppressWarnings({"all"})
public class Properties_ {public static void main(String[] args) {//老韩解读//1. Properties 继承 Hashable//2. 可以通过 k-v 存放数据, 当然key 和 value 不能为 null//增加Properties properties = new Properties();//properties.put(null, "abc");    //抛出空指针异常//properties.put("abc", null);    //抛出 空指针异常properties.put("john", 100);//k-vproperties.put("lucy", 100);properties.put("lic", 100);properties.put("lic", 88);  //如果有相同的key, value被替换System.out.println("properties=" + properties);//通过k 获取对应值System.out.println(properties.get("lic"));  //88//删除properties.remove("lic");System.out.println("properties=" + properties);//修改properties.put("john", "约翰");System.out.println("properties=" + properties);}
}

Treeset的相关用法

  • TreeSet的使用案例
package com.hspedu.set_;import java.util.Comparator;
import java.util.TreeSet;@SuppressWarnings({"all"})
public class TreeSet_ {public static void main(String[] args) {//老韩解读//1. 当我们使用无参构造器, 创建TreeSet时, 仍然是无序的//2. 老师希望添加的元素, 按照字符串大小来排序//3. 使用TreeSet 提供的一个构造器, 可以传入一个比较器(匿名内部类)//  并指定排序规则//4. 简单看看源码//  TreeSet treeSet = new TreeSet();TreeSet treeSet = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {//下面 调用String的 compareTo方法进行字符号串大小比较//如果老韩要求加入的元素, 按照长度大小排序//return ((String) o1).compareTo((String)o2);return ((String) o2).length() - ((String) o1).length();}});//添加数据treeSet.add("jack");treeSet.add("tom"); //长度3treeSet.add("sp");treeSet.add("a");treeSet.add("abc"); //长度3,compare()认为长度相等的元素为相同的元素,则abc不会添加System.out.println("treeSet=" + treeSet);//老韩解读/*1. 构造器把传入的比较器对象, 赋给了 TreeSet的底层的 TreeMap的属性 this.comparatorpublic TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}2.在 调用 treeSet.add("tom"), 在底层会执行到if (cpr != null) {  //cpr 就是我们的匿名内部类(对象)do {parent = t;// 动态绑定到我们的匿名内部类(对象)comparecmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;else    //如果相等, 即返回0, 这个Key就没有加入return t.setValue(value);} while (t != null);}*/}
}

总结-开发中如何选择集合实现类(记住)

Collections工具类

  • Collection工具类介绍
    1)Collection是一个操作Set、List和Map等集合的工具类
    2)Collection中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作

  • 排序操作:(均为static方法)
    1)reverse(List): 反转List中元素的顺序
    2)shuffle(List):对List集合进行随机排序
    3)sort(List): 根据元素的自然顺序对指定List集合元素按升序排序
    4)sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
    5)swap(List, int, int):将指定list集合中的i处元素和j处元素进行交换

案例演示:

package com.hspedu.collections_;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;@SuppressWarnings({"all"})
public class Collections_ {public static void main(String[] args) {//创建ArrayList 集合,用于测试List list = new ArrayList();list.add("tom");list.add("smith");list.add("king");list.add("milan");//        reverse(List): 反转List中元素的顺序Collections.reverse(list);System.out.println("list=" + list);
//        shuffle(List):对List集合进行随机排序
//        for (int i = 0; i < 5; i++) {//            Collections.shuffle(list);
//            System.out.println("list=" + list);
//        }
//        sort(List): 根据元素的自然顺序对指定List集合元素按升序排序Collections.sort(list);System.out.println("自然排序后");System.out.println("list=" + list);
//        sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序//我们希望按照 字符串的长度大小排序Collections.sort(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {//可以加入校验代码return ((String)o1).length() - ((String)o2).length();}});System.out.println("字符串长度大小排序=" + list);
//        swap(List, int, int):将指定list集合中的i处元素和j处元素进行交换//比如Collections.swap(list, 0, 1);System.out.println("交换后的情况");System.out.println("list=" + list);}
}
  • 查找、替换

案例演示:

package com.hspedu.collections_;import java.util.*;@SuppressWarnings({"all"})
public class Collections_ {public static void main(String[] args) {//创建ArrayList 集合,用于测试List list = new ArrayList();list.add("tom");list.add("smith");list.add("king");list.add("milan");list.add("tom");//Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素System.out.println("自然排序最大元素=" + Collections.max(list));//Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素//比如, 我们要返回长度最大的元素Object maxObject = Collections.max(list, new Comparator(){@Overridepublic int compare(Object o1, Object o2) {return ((String)o1).length() - ((String)o2).length();}});System.out.println("长度最大的元素=" + maxObject);//Object min(Collection)//Object min(Collection,Comparator)//上面的两个方法,参考max即可//int frequency(Collection,Object):返回指定集合中指定元素的出现次数System.out.println("tom出现的次数=" + Collections.frequency(list, "tom"));//void copy(List dest,List src):将src中的内容复制到dest中ArrayList dest = new ArrayList();//为了完成一个完整拷贝, 我们需要先给dest赋值, 大小和list.size()一样for (int i = 0; i < list.size(); i++) {dest.add("");}//拷贝Collections.copy(dest, list);System.out.println("dest=" + dest);//boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值//如果list中, 有tom 就替换成汤姆Collections.replaceAll(list, "tom", "汤姆");System.out.println("list替换后=" + list);}
}

章节作业

日期

第12章 2022年5月23日
第13章 2022年5月24日-2022年5月25日
2022年5月28日-2022年5月29日
第14章 2022年5月30日- 2022年6月7日

Java笔记(韩顺平Java基础12-14章)相关推荐

  1. 韩顺平 java坦克大战_坦克大战完整版(韩顺平java)

    [实例简介] 坦克大战完整源代码(韩顺平java视频配套) [实例截图] [核心代码] 5i86q5 └── 源码 └── Class14 ├── 111.wav ├── bin │   ├── bo ...

  2. 适合有编程基础的人看的《韩顺平零基础30天学java》笔记(P104~P129)

    写在最前边: 研究生一枚,为后端实习和未来工作打基础.无意间发现韩顺平老师的课程,细心细致,讲课和吴恩达老师一样,都是保姆式讲解,各种基础知识都会补充,爱了. 韩顺平老师课程地址:https://ww ...

  3. Java笔记(韩顺平Java基础7-8章)

    Java学习笔记(第7章 P191-P263)(第8章 P264-P360) 第7章 面向对象编程(基础部分) 类与对象 成员方法 成员方法传参机制(!!!) 方法递归调用(!!!) 方法重载(Ove ...

  4. Java笔记(韩顺平Java基础3-4章)

    Java学习笔记(第3章 P35-P62 )(第4章 P63-P103) 第3章 变量 变量的使用注意事项 程序中 + 号的使用 数据类型 整数类型 浮点类型 字符类型(char) 布尔类型:bool ...

  5. 韩顺平java基础——坦克大战(含有线程、I\O流的讲解)

    写在最前边: 研究生一枚,为后端实习和未来工作打基础.无意间发现韩顺平老师的课程,细心细致,讲课和吴恩达老师一样,都是保姆式讲解,各种基础知识都会补充,爱了. 韩顺平老师课程地址:https://ww ...

  6. 韩顺平Java自学笔记 反射

    一.反射入门案例 目录 一.反射入门案例 二.反射的机制 1.反射的原理 2.反射相关的类 3.反射的优点和缺点 三.Class类详解 1.Class类的特征 2.Class的常用方法 3.获取Cla ...

  7. 韩顺平Java基础-第一阶段(建立编程思想)

    目录 第 2 章 Java概述 第 3 章 变量 第 4 章 运算符 第 5 章 控制结构 第 6 章 数组,排序和查找 第 7 章 面向对象编程(基础) 第 8 章 面向对象编程(中级) 第 9 章 ...

  8. 韩顺平Java自学笔记 项目 QQ聊天室

    目录 一.项目前的准备 1.为什么选择这个项目 2.项目开发的流程 3.项目的需求 二.开发阶段 1.登录功能实现 2.拉取在线用户实现 3.无异常退出的实现 4.私聊功能的实现 5.群发的实现 6. ...

  9. 韩顺平java笔记 第1讲 内容介绍 项目演示 原理剖析

    1.java介绍 sun公司  gosling 1990  sun启动绿色计划 1992 创建aok语言---->java 1994 gosling 参加硅谷大会 演示java功能 震惊世界 1 ...

最新文章

  1. 程序员缺乏经验的 7 种表现!
  2. eselasticsearch入门_ElasticSearch入门 附.Net Core例子
  3. TensorFlow 合并与分割
  4. Centos7之Gcc安装
  5. CodeForces - 1358D The Best Vacation(前缀和+尺取)
  6. 爬虫 spider09——爬取指定数据,去重复,并存储到mysql
  7. Spark MLlib学习
  8. mysql数据表最高速迁移,mysql的存储引擎为:myisam
  9. 数字图像处理 空间域锐化 MATLAB实验
  10. Nginx 500错误总结
  11. 【学习Spring框架】依赖注入和控制反转异同?
  12. Web性能优化:雅虎35条
  13. sdk的安装与环境配置
  14. 保持简单----纪念丹尼斯•里奇(Dennis Ritchie
  15. Chrome 开发者工具 network 显示 Provisional headers are shown 的几种原因
  16. 【计算机网络】网络层 : 子网划分 ( 三级 IP 地址 | 子网划分 | 子网掩码 | 子网掩码计算示例 | 子网的分组转发 )★
  17. 盒子模型(标准盒模型、怪异盒模型)
  18. mysql复制--主从复制配置
  19. ARM CORTEX-M3简介
  20. 如何轻松搭建一个在线wiki文档平台?

热门文章

  1. 基于xpath,多线程,爬取豆瓣250电影的海报
  2. 手机是否已被他人监控了?如果出现这3种现象,大家还是小心点
  3. 2022年JCR新功能更新了,新增的指标JCI究竟是什么含义?
  4. SAP License:BCS进阶第二篇-BCS业务篇
  5. vi设计中视觉识别符号设计与商标设计的区别
  6. 2018,Java程序猿一定要做的6件事
  7. 深度学习 第3章线性分类 实验四 pytorch实现 Logistic回归 上篇
  8. Android开发 camera被占用的问题
  9. 【Windows 问题系列第 16 篇】如何去除 Chrome 中的请停用以开发者模式运行的扩展程序
  10. VsCode反应较慢(vscode卡顿,反应慢)