Java工程师进阶之路 - 模块三(Java核心类库(上))

Java核心类库(上)

任务一:常用类的概述和使用

第一节:常用的包(熟悉

包的名称和功能
  • java.lang包 - 该包是Java语言的核心包,并且该包中的所有内容由Java虚拟机自动导入
    如:System类、String类、…
  • java.util包 - 该包是Java语言的工具包,里面提供了大量工具类以及集合类等
    如:Scanner类、Random类、List集合、…
  • java.io包 - 该包是Java语言中的输入输出包,里面提供了大量读写文件相关的类等
    如:FileInputStream类、FileOutputStream类、…
  • java.net包 - 该包是Java语言中的网络包,里面提供了大量网络编程相关的类等
    如:ServerSocket类、Socket类、…
  • java.sql 包 - 该包是Java语言中的数据包,里面提供了大量操作数据库的类和接口等
    如:DriverManager类、Connection接口、…
  • … …
  • Java程序员在编程时可以使用大量类库,因此Java编程时需要记的很多,对编程能力本身要求不是特别的高。

第二节: Object类的概述(重点

基本概念
  • java.lang.Object类是Java语言中类层次结构的根类,也就是说任何一个类都是该类的直接或者间接子类
  • 如果定义一个Java类时没有使用extends关键字声明其父类则其父类为 java.lang.Object 类
  • Object类定义了“对象”的基本行为被子类默认继承
常用的方法
方法声明功能介绍
Object()使用无参方式构造对象。
boolean equals(Object obj)用于判断调用对象是否与参数对象相等。
该方法默认比较两个对象的地址是否相等,与 == 运算符的结果一致。
若希望比较两个对象的内容,则需要重写该方法。
若该方法被重写后,则应该重写hashCode方法来保证结果的一致性
int hashCode()用于获取调用对象的哈希码值(内存地址的编号)。
若两个对象调用equals方法相等,则各自调用该方法的结果必须相同。
若两个调用对象equals方法不相等,则各自调用该方法的结果应该不相同。
为了使得该方法与equals方法保持一致,需要重写该方法
String toString()用于获取调用对象的字符串形式。
该方法默认返回的字符串为:包名.类名@哈希码值的十六进制。
为了返回更有意义的数据,需要重写该方法。
使用print或println打印引用或字符串拼接引用都会自动调用该方法。
Class getClass()用于返回调用对象执行时的Class实例,反射机制使用。

equals方法的原理

01 equals方法的原理分析

案例题目:

  • 编程实现Student类的封装,特征:学号(id)和姓名,要求提供打印所有特征的方法。
  • 编程实现StudentTest类,在main方法中使用有参方式构造两个Student类型的对象并打印特征。

题目扩展

  • 如何实现以姓名作为基准判断两个对象是否相等?以及以学号和姓名同时作为基准判断两个对象是否相等?

第三节:包装类(熟悉

包装类的概念
  • 通常情况下基本数据类型的变量不是对象,为了满足万物皆对象的理念就需要对基本数据类型的变量进行打包封装处理变成对象,而负责将这些变量声明为成员变量进行对象化处理的相关类,叫做包装类
    如:
// 包装类
Person p = new Person();
// 基本
int num = 10;
// 自定义打包封装处理基本数据类型变量的类
public class MyInt {
    private int num = 10;
}
包装类的分类
包装类对应的基本类型直接父类
java.lang.Bytebytejava.lang.Number
java.lang.Shortshortjava.lang.Number
java.lang.Integerintjava.lang.Number
java.lang.Longlongjava.lang.Number
java.lang.Floatfloatjava.lang.Number
java.lang.Doubledoublejava.lang.Number
java.lang.Booleanboolean
java.lang.Characterchar
Integer类的概述
(1)基本概念
  • java.lang.Integer类内部包装了一个int类型的变量作为成员变量,主要用于实现对int类型的包装提供int类型到String类之间的转换等方法
(2)常用的常量
常量类型和名称功能介绍
public static final int MAX_VALUE表示int类型可以描述的最大值,即2^31-1
public static final int MIN_VALUE表示int类型可以描述的最小值,即-2^31
public static final int SIZE表示int类型采用二进制补码形式的位数
public static final int BYTES表示int类型所占的字节个数
public static final Class TYPE表示int类型的Class实例
(3)常用的方法
方法声明功能介绍
Integer(int value)根据参数指定的整数来构造对象(已过时)
Integer(String s)根据参数指定的字符串来构造对象 (已过时)
int intValue()获取调用对象中的整数值并返回
static Integer valueOf(int i)根据参数指定整数值得到Integer类型对象
boolean equals(Object obj)比较调用对象与参数指定的对象是否相等
String toString()返回描述调用对象数值的字符串形式
static int parseInt(String s)将字符串类型转换为int类型并返回
static String toString(int i)获取参数指定整数的十进制字符串形式
static String toBinaryString(int i)获取参数指定整数的二进制字符串形式
static String toHexString(int i)获取参数指定整数的十六进制字符串形式
static String toOctalString(int i)获取参数指定整数的八进制字符串形式
(4)装箱和拆箱的概念
  • Java5发布之前使用包装类对象进行运算时,需要较为繁琐的“拆箱”和“装箱”操作;即运算前先将包装类对象拆分为基本类型数据,运算后再将结果封装成包装类对象。
  • 从Java5开始增加了自动拆箱自动装箱的功能。
(5)自动装箱池
  • 在Integer类的内部提供了自动装箱池技术,将**-128到127**之间的整数已经装箱完毕,当程序中使用该范围之间的整数时,无需装箱直接取用自动装箱池中的对象即可,从而提高效率。

  • 装箱和拆箱的笔试考点:

Integer it6 = 127;
//128;
Integer it7 = 127;
//128;
Integer it8 = new Integer(127);
//new Integer(128);
Integer it9 = new Integer(127);
//new Integer(128);
System.out.println(it6 == it7);
// 比较地址  false  true  地址一样
System.out.println(it6.equals(it7));
// 比较内容  true
System.out.println(it8 == it9);
// 比较地址  false
System.out.println(it8.equals(it9));
// 比较内容  true
Double类的概述
(1)基本概念
  • java.lang.Double类型内部包装了一个double类型的变量作为成员变量,主要用于实现对double类型的包装提供double类型到String类之间的转换等方法
(2)常用的常量
常量类型和名称功能介绍
public static final int SIZE表示double类型的二进制位数
public static final int BYTES表示double类型的字节个数
public static final Class TYPE表示double类型的Class实例
(3)常用的方法
方法声明功能介绍
Double(double value)根据参数指定的浮点数据来构造对象(已过时)
Double(String s)根据参数指定的字符串来构造对象 (已过时)
double doubleValue()获取调用对象中的浮点数据并返回
static Double valueOf(double d)根据参数指定浮点数据得到Double类型对象
boolean equals(Object obj)比较调用对象与参数指定的对象是否相等
String toString()返回描述调用对象数值的字符串形式
static double parseDouble(String s)将字符串类型转换为double类型并返回
boolean isNaN()判断调用对象的数值是否为非数字
  • 扩展:

    java.lang.Number类是个抽象类,是上述类的父类来描述所有类共有的成员

Boolean类的概述
(1)基本概念
  • java.lang.Boolean类型内部包装了一个boolean类型的变量作为成员变量,主要用于实现对boolean类型的包装提供boolean类型到String类之间的转换等方法
(2)常用的常量
常量类型和名称功能介绍
public static final Boolean FALSE对应基值为false的对象
public static final Boolean TRUE对应基值为true的对象
public static final Class TYPE表示boolean类型的Class实例
(3)常用的方法
方法声明功能介绍
Boolean(boolean value)根据参数指定的布尔数值来构造对象(已过时)
Boolean(String s)根据参数指定的字符串来构造对象 (已过时)
boolean booleanValue()获取调用对象中的布尔数值并返回
static Boolean valueOf(boolean b)根据参数指定布尔数值得到Boolean类型对象
boolean equals(Object obj)比较调用对象与参数指定的对象是否相等
String toString()返回描述调用对象数值的字符串形式
static boolean parseBoolean(String s)将字符串类型转换为boolean类型并返回
Character类的概述
( 1 )基本概念
  • java.lang.Character类型内部包装了一个char类型的变量作为成员变量,主要用于实现对char类型的包装提供字符类别的判断和转换等方法
( 2 )常用的常量
常量类型和名称功能介绍
public static final int SIZE表示char类型的二进制位数
public static final int BYTES表示char类型的字节个数
public static final Class TYPE表示char类型的Class实例
( 3 )常用的方法
方法声明功能介绍
Character(char value)根据参数指定的字符数据来构造对象(已过时)
char charValue()获取调用对象中的字符数据并返回
static Character valueOf(char c)根据参数指定字符数据得到Character类型对象
boolean equals(Object obj)比较调用对象与参数指定的对象是否相等
String toString()返回描述调用对象数值的字符串形式
static boolean isUpperCase(char ch)判断参数指定字符是否为大写字符
static boolean isLowerCase(char ch)判断参数指定字符是否为小写字符
static boolean isDigit(char ch)判断参数指定字符是否为数字字符
static char toUpperCase(char ch)将参数指定的字符转换为大写字符
static char toLowerCase(char ch)将参数指定的字符转换为小写字符
包装类(Wrapper)的使用总结
  • 基本数据类型转换为对应包装类的方式

    调用包装类的构造方法或静态方法即可

  • 获取包装类对象中基本数据类型变量数值的方式

    调用包装类中的xxxValue方法即可

  • 字符串转换为基本数据类型的方式

    调用包装类中的parseXxx方法即可

第三节:数学处理类(熟悉

Math类的概述
( 1 )基本概念
  • java.lang.Math类主要用于提供执行数学运算的方法,如:对数,平方根。
( 2 )常用的方法
方法声明功能介绍
static int max(int a, int b)返回两个参数中的最大值
static int min(int a, int b)返回两个参数中的最小值
static double pow(double a, double b)返回第一个参数的第二个参数次幂
static int abs(int a)返回参数指定数值的绝对值
static long round(double a)返回参数四舍五入的结果
static double sqrt(double a)返回参数的平方根
static double random()返回0.0到1.0的随机数
BigDecimal类的概述
( 1 )基本概念
  • 由于float类型和double类型在运算时可能会有误差,若希望实现精确运算借助java.math.BigDecimal类型加以描述。
( 2 )常用的方法
方法声明功能介绍
BigDecimal(String val)根据参数指定的字符串来构造对象
BigDecimal add(BigDecimal augend)用于实现加法运算
BigDecimal subtract(BigDecimal subtrahend)用于实现减法运算
BigDecimal multiply(BigDecimal multiplicand)用于实现乘法运算
BigDecimal divide(BigDecimal divisor)用于实现除法运算

(4)注意事项

  • 代码:
BigDecimal bd5 = new BigDecimal("2");
BigDecimal bd6 = new BigDecimal("0.3");
// 结果四舍五入
System.out.println("除法运算的结果是:" + bd5.divide(bd6, RoundingMode.HALF_UP));

RoundingMode 常量:

常量描述
CEILING向正无穷方向舍入,向正最大方向靠拢,如果是正数,舍入行为类似于UP;
如果是负数,则舍入行为类似于DOWN;
注意,Math.round() 方法使用的即此模式
UP远离零方向舍入,向远离0的方向舍入,也就是说,向绝对值最大的方向舍入,只要舍弃位非0即进位
DOWN趋向零方向的舍入,向0方向靠拢,也就是说,向绝对值最小的方向输入;
注意,所有的位都舍弃不存在进位的情况
FLOOR向负无穷方向舍入,向负无穷方向靠拢,如果是正数,则舍入行为类似于DOWN;
如果是负数,则舍入行为类似于UP
HALF_DOWN最近数字舍入(5舍),在四舍五入中,5是进位的,而在HALF_DOWN中却是舍弃不进位。
HALF_EVEN银行家算法,四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一
HALF_UP舍入模式向“最近邻居”舍入,除非两个邻居等距,在这种情况下向上舍入即四舍五入
UNNECESSARY舍入模式断言所请求的操作具有精确结果,因此不需要舍入
BigInteger类的概念
( 1 )基本概念
  • 若希望表示比long类型范围还大的整数数据,则需要借助java.math.BigInteger类型描述。
( 2 )常用的方法
方法声明功能介绍
BigInteger(String val)根据参数指定的字符串来构造对象
BigInteger add(BigInteger val)用于实现加法运算
BigInteger subtract(BigInteger val)用于实现减法运算
BigInteger multiply(BigInteger val)用于实现乘法运算
BigInteger divide(BigInteger val)用于实现除法运算
BigInteger remainder(BigInteger val)用于实现取余运算
BigInteger[] divideAndRemainder(BigInteger val)用于实现取商和余数的运算

任务二:String类的概述和使用

第一节:String类的概念(重点

  • java.lang.String类用于描述字符串,Java程序中所有的字符串字面值都可以使用该类的对象加以描述,如:“abc”。

  • 该类由final关键字修饰,表示该类不能被继承

  • 从jdk1.9开始该类的底层不使用char[]来存储数据,而是改成 byte[]加上编码标记,从而节约了一些空间

  • 该类描述的字符串内容是个常量不可更改,因此可以被共享使用。如:

String str1 = “abc”;	// 其中"abc"这个字符串是个常量不可改变。
str1 =123;			// 将“123”字符串的地址赋值给变量str1。
                        // 改变str1的指向并没有改变指向的内容
  • 图解Str1字的变化:

01 String类型引用的指向改变

第二节:常量池的概念(原理

  • 由于String类型描述的字符串内容是常量不可改变,因此Java虚拟机将首次出现的字符串放入常量池中,若后续代码中出现了相同字符串内容则直接使用池中已有的字符串对象而无需申请内存及创建对象,从而提高了性能

第三节:常用的构造方法(练熟、记住

方法声明功能介绍
String()使用无参方式构造对象得到空字符序列
String(byte[] bytes, int offset, int length)使用bytes数组中下标从offset位置开始的length个字节来构造对象
String(byte[] bytes)使用bytes数组中的所有内容构造对象
String(char[] value, int offset, int count)使用value数组中下标从offset位置开始的count个字符来构造对象
String(char[] value)使用value数组中的所有内容构造对象
String(String original)根据参数指定的字符串内容来构造对象,新创建对象为参数对象的副本
String 笔试考点
  • 代码:
public class StringExamTest {

    public static void main(String[] args) {
		// 1.请问下面的代码会创建几个对象?分别存放在什么地方?
		// 1个对象  存放在常量池中
		//String str1 = "hello";
		//String str1 = new String("helo");

		// 2.常量池和堆区对象的比较
		String str1 = "hello"; 
		// 常量池
		String str2 = "hello"; 
		// 常量池
		String str3 = new String("hello");
		// 堆区
		String str4 = new String("hello");
		// 堆区

		System.out.println(str1 == str2);      
		// 比较地址  true
		System.out.println(str1.equals(str2)); 
		// 比较内容  true
		System.out.println(str3 == str4);      
		// 比较地址  false
		System.out.println(str3.equals(str4)); 
		// 比较内容  true
		System.out.println(str2 == str4);      
		// 比较地址  false
		System.out.println(str2.equals(str4)); 
		// 比较内容 true

		System.out.println("------------------------------------------------------------");

		// 3.常量有优化机制,变量没有
		String str5 = "abcd";
		// 常量优化机制自动编译成"abcd",直接使用常量池中的"abcd"
		String str6 = "ab" + "cd";
		System.out.println(str5 == str6);
		// 比较地址  true

		String str7 = "ab";
		String str8 = str7 + "cd";
		// 没有常量优化
		System.out.println(str5 == str8);
		// 比较地址 false
    }
}

第四节:常用的成员方法(练熟、记住

方法声明功能介绍
String toString()返回字符串本身
byte[] getBytes()将当前字符串内容转换为byte数组并返回
char[] toCharArray()用于将当前字符串内容转换为char数组并返回
方法声明功能介绍
char charAt(int index)方法charAt用于返回字符串指定位置的字符。
int length()返回字符串字符序列的长度
boolean isEmpty()判断字符串是否为空
  • 案例题目

    判断字符串“上海自来水来自海上”是否为回文并打印,所谓回文是指一个字符序列无论从左向右读还是从右向左读都是相同的句子。

public class StringJudgeTest {

    public static void main(String[] args) {
        // 1.创建字符串对象并打印
        String str1 = new String("上海自来水来自海上");
        System.out.println("str1 = " + str1);
        // 上海自来水来自海上   9

        // 2.判断该字符串内容是否为回文并打印
        for (int i = 0; i < str1.length() / 2; i++) {
            if (str1.charAt(i) != str1.charAt(str1.length() - i - 1)) {
                // 0和8   1和7  2和6  3和5
                System.out.println(str1 + " 不是回文!");
                // 仅仅是用于实现方法的结束
                return;
            }
        }
        System.out.println(str1 + " 是回文!");
    }
}
方法声明功能介绍
int compareTo(String anotherString)用于比较调用对象和参数对象的大小关系
int compareToIgnoreCase(String str)不考虑大小写,也就是’a’和’A’是相等的关系
  • 案例题目

    编程实现字符串之间大小的比较并打印。

public class StringCompareTest {

    public static void main(String[] args) {
		// 1.构造String类型的对象并打印
        String str1 = new String("hello");
        System.out.println("str1 = " + str1);
		// hello

		// 2.使用构造好的对象与其它字符串对象之间比较大小并打印
        // 按字典顺序挨个比较,只要有一位不相同就将该位字符ASCII值相减的值返回,
        // 否则若出现字符串前面相同长度不同就将长度相减的值返回
        // 'h' - 'w' => 104 - 119 => -15
        System.out.println(str1.compareTo("world"));
        // 'e' - 'a' => 101 - 97  => 4
        System.out.println(str1.compareTo("haha"));
        // 'l' - 'h' => 108 - 104 => 4
        System.out.println(str1.compareTo("hehe"));
        // 'l' - 'i' => 108 - 105 => 3
        System.out.println(str1.compareTo("heihei"));
        // 长度: 5 - 10 => -5
        System.out.println(str1.compareTo("helloworld"));
        System.out.println(str1.compareToIgnoreCase("HELLO"));
		// 0
    }
}
方法声明功能介绍
String concat(String str)用于实现字符串的拼接
boolean contains(CharSequence s)用于判断当前字符串是否包含参数指定的内容
String toLowerCase()返回字符串的小写形式
String toUpperCase()返回字符串的大写形式
String trim()返回去掉前导和后继空白的字符串
boolean startsWith(String prefix)判断字符串是否以参数字符串开头
boolean startsWith(String prefix, int offset)从指定位置开始是否以参数字符串开头
boolean endsWith(String suffix)判断字符串是否以参数字符串结尾
  • 案例题目

    编程实现上述方法的使用。

方法声明功能介绍
boolean equals(Object anObject)用于比较字符串内容是否相等并返回
int hashCode()获取调用对象的哈希码值
boolean equalsIgnoreCase(String anotherString)用于比较字符串内容是否相等并返回,不考虑大小写,如:'A’和’a’是相等
  • 案例题目

    提示用户从键盘输入用户名和密码信息,若输入”admin”和”123456”则提示“登录成功,欢迎使用”,否则提示“用户名或密码错误,您还有n次机会”,若用户输入三次后依然错误则提示“账户已冻结,请联系客服人员!”

public class StringEqualsTest {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        for (int i = 3; i > 0; i--) {
            // 1.提示用户从键盘输入用户名和密码信息并使用变量记录
            System.out.println("请输入您的用户名和密码信息:");
            String userName = sc.next();
            String password = sc.next();

            // 2.判断用户名和密码是否为"admin"和"123456"并给出提示
            //if ("admin".equals(userName) && "123456".equals(password)) {
            if ("admin".equalsIgnoreCase(userName) && "123456".equals(password)) {
                // 防止空指针异常
                System.out.println("登录成功,欢迎使用!");
                break;
            }
            //else {
            if (1 == i) {
                System.out.println("账户已冻结,请联系客服人员!");
            } else {
                System.out.println("用户名或密码错误,您还有" + (i - 1) + "次机会!");
            }
            //}
        }

        // 关闭扫描器
        sc.close();
    }
}
方法声明功能介绍
int indexOf(int ch)用于返回当前字符串中参数ch指定的字符第一次出现的下标
int indexOf(int ch, int fromIndex)用于从fromIndex位置开始查找ch指定的字符
int indexOf(String str)在字符串中检索str返回其第一次出现的位置,若找不到返回-1
int indexOf(String str, int fromIndex)表示从字符串的fromIndex位置开始检索str第一次出现的位置
int lastIndexOf(int ch)用于返回参数ch指定的字符后一次出现的下标
int lastIndexOf(int ch, int fromIndex)用于从fromIndex位置开始查找ch指定字符出现的下标
int lastIndexOf(String str)返回str指定字符串后一次出现的下标
int lastIndexOf(String str, int fromIndex)用于从fromIndex位置开始反向搜索的第一次出现的下标。
  • 案例题目

    编写通用的代码可以查询字符串"Good Good Study, Day Day Up!"中所有"Day"出现的索引位置并打印出来。

String str1 = "Good Good Study, Day Day Up!";
// 编写通用代码实现将字符串str1中所有"Day"出现的索引位置找到并打印出来
int pos = str1.indexOf("Day");
while (-1 != pos) {
    System.out.println("pos = " + pos);
    // 17
    pos = str1.indexOf("Day", pos + 1);
}

// 优化一下
pos = 0;
while ((pos = str1.indexOf("Day", pos)) != -1) {
    System.out.println("pos = " + pos);
    pos += "Day".length();
}
方法声明功能介绍
String substring(int beginIndex, int endIndex)返回字符串中从下标beginIndex(包括)开始到 endIndex(不包括)结束的子字符串
String substring(int beginIndex)返回字符串中从下标beginIndex(包括)开始到字符串结尾的子字符串
  • 案例题目

    提示用户从键盘输入一个字符串和一个字符,输出该字符(不含)后面的所有子字符串。

3.获取输入字符串中从输入字符(不含)起的子字符串内容
System.out.println("请输入一个字符串:");
Scanner sc = new Scanner(System.in);
String str4 = sc.next();
System.out.println("请输入一个字符:");
String str5 = sc.next();

// 从str4中查找str5第一次出现的索引位置
int pos = str4.indexOf(str5);
System.out.println("pos = " + pos);

// 根据该位置获取子字符串
String str6 = str4.substring(pos + 1);
System.out.println("获取到的子字符串是:" + str6);

第五节: 正则表达式的概念(了解

  • 正则表达式本质就是一个 “规则字符串” ,可以用于对字符串数据的格式进行验证,以及匹配、查找、替换等操作。该字符串通常使用**^运算符作为开头标志**,使用**$运算符作为结尾标志**,当然也可以省略

第六节:正则表达式的规则(了解

正则表达式说明
[abc]可以出现a、b、c中任意一个字符
[^abc]可以出现任何字符,除了a、b、c的任意字符
[a-z]可以出现a、b、c、……、z中的任意一个字符
[a-zA-Z0-9]可以出现az、AZ、0~9中任意一个字符
正则表达式说明
.任意一个字符(通常不包含换行符)
\d任意一个数字字符,相当于[0-9]
\D任意一个非数字字符
\s空白字符,相当于[\t\n\x0B\f\r]
\S非空白字符
\w任意一个单词字符,相当于[a-zA-Z_0-9]
\W任意一个非单词字符
正则表达式说明
X?表示X可以出现一次或一次也没有,也就是0 ~ 1次
X*表示X可以出现零次或多次,也就是0 ~ n次
X+表示X可以出现一次或多次,也就是1 ~ n次
X{n}表示X可以出现恰好 n 次
X{n,}表示X可以出现至少 n 次,也就是>=n次
X{n,m}表示X可以出现至少 n 次,但是不超过 m 次,也就是>=n并且<=m次

第七节: 正则表达式相关的方法(熟悉

方法名称方法说明
boolean matches(String regex)判断当前正在调用的字符串是否匹配参数指定的正则表达式规则
  • 案例题目

    使用正则表达式描述一下银行卡密码的规则:要求是由6位数字组成。

    使用正则表达式描述一下QQ号码的规则:要求是由非0开头的5~15位数组成。

    使用正则表达式描述一下手机号码的规则:要求是由1开头,第二位数是3、4、5、7、8中的一位,总共11位

    描述身份证号码的规则:总共18位,6位数字代表地区,4位数字代表年,2位数字代表月,2位数字代表日期, 3位数字代表个人,最后一位可能数字也可能是X。

public static void main(String[] args) {

    // 1.定义描述规则的正则表达式字符串并使用变量记录
    // 正则表达式只能对数据格式进行验证,无法对数据内容的正确性进行检查,
    // 内容的正确性检查需要后台查询数据库
    // 描述银行卡密码的规则:由6位数字组成
    ///String reg = "^[0-9]{6}$";
    ///String reg = "[0-9]{6}";
    ///String reg = "\\d{6}";
    // 使用正则表达式描述一下QQ号码的规则:要求是由非0开头的5~15位数字组成。
    ///String reg = "[1-9]\\d{4,14}";
    // 使用正则表达式描述一下手机号码的规则:要求是由1开头,第二位数是3、4、5、7、8中的一位,总共11位
    String reg = "1[34578]\\d{9}";
    // 描述身份证号码的规则:总共18位,6位数字代表地区,4位数字代表年,
    // 2位数字代表月,2位数字代表日期, 3位数字代表个人,
    // 最后一位可能数字也可能是X。
    reg = "(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9|X,x])";

    // 2.提示用户从键盘输入指定的内容并使用变量记录
    Scanner sc = new Scanner(System.in);
    while (true) {
        ///System.out.println("请输入您的银行卡密码:");
        ///System.out.println("请输入您的QQ号码:");
        ///System.out.println("请输入您的手机号码:");
        System.out.println("请输入您的身份证号码:");
        String str = sc.next();
        // 3.判断用户输入的字符串内容是否满足指定的规则并打印
        if (str.matches(reg)) {
            ///System.out.println("银行卡密码的格式正确!");
            System.out.println("输入字符串的格式正确!");
            break;
        } else {
            ///System.out.println("银行卡密码的格式错误!");
            System.out.println("输入字符串的格式错误!");
        }
    }
}
方法名称方法说明
String[] split(String regex)参数regex为正则表达式,以regex所表示的字符串为分隔符,将字符串拆分成字符串数组
String replace(char oldChar, char newChar)使用参数newChar替换此字符串中出现的所有参数oldChar
String replaceFirst(String regex, String replacement)替换此字符串匹配给定的正则表达式的第一个子字符串
String replaceAll(String regex, String replacement)将字符串中匹配正则表达式regex的字符串替换成 replacement

任务三:可变字符串类和日期相关类

第一节:可变字符串类(重点

基本概念
  • 由于String类描述的字符串内容是个常量不可改变,当需要在Java代码中描述大量类似的字符串时,只能单独申请和存储,此时会造成内存空间的浪费
  • 为了解决上述问题,可以使用java.lang.StringBuilder类和java.lang.StringBuffer类来描述字符序列可以改变的字符串,如:“ab”。
  • StringBuffer类是从jdk1.0开始存在,属于线程安全的类,因此效率比较低
  • StringBuilder类是从jdk1.5开始存在,属于非线程安全的类,效率比较高
StringBuilder类常用的构造方法
方法声明功能介绍
StringBuilder()使用无参方式构造对象,容量为16
StringBuilder(int capacity)根据参数指定的容量来构造对象,容量为参数指定大小
StringBuilder(String str)根据参数指定的字符串来构造对象,容量为:16+字符串长度
StringBuilder类常用的成员方法
方法声明功能介绍
int capacity()用于返回调用对象的容量
int length()用于返回字符串的长度,也就是字符的个数
StringBuilder insert(int offset, String str)插入字符串并返回调用对象的引用,就是自己。
StringBuilder append(String str)追加字符串
StringBuilder deleteCharAt(int index)将当前字符串中下标为index位置的单个字符删除
StringBuilder delete(int start,int end)删除字符串
StringBuilder replace(int start,int end,String str)替换字符串
StringBuilder reverse()字符串反转
  • 注意

    作为参数传递的话,方法内部String不会改变其值StringBuffer和StringBuilder会改变其值。

    StringBuilder一旦里面字符串的长度超过容量就会自动扩容为原来的两倍+2若容量还不够就直接使用当前存放的字符串的长度

返回值的设计
  • StringBuilder的很多方法的返回值均为StringBuilder类型。这些方法的返回语句均为:return this
  • 由此可见,这些方法在对StringBuilder所封装的字符序列进行改变后又返回了该对象的引用。基于这样设计的目的在于可以连续调用
笔试考点
  • 代码:
// 考点一:既然StringBuilder类的对象本身可以修改,那么为什么成员方法还有返回值呢?
// 解析:为了连续调用
sb3.reverse().append("1").append("2").insert(0, "3").delete(0, 1).reverse();
// 考点二:如何实现StringBuilder类型和String类型之间的转换呢?
String str3 = sb3.toString();
StringBuilder sb5 = new StringBuilder(str3);
// 考点三:String、StringBuilder、StringBuffer之间效率谁高?排列如何?
// String < StringBuffer < StringBuilder

第二节:Java8之前的日期相关类(熟悉

System类的概述
(1)基本概念
  • Java.lang.System类中提供了一些有用的类字段和方法
(2)常用的方法
方法声明功能介绍
static long currentTimeMillis()返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
Date类的概述
(1)基本概念
  • java.util.Date类主要用于描述特定的瞬间,也就是年月日时分秒,可以精确到毫秒
(2)常用的方法
方法声明功能介绍
Date()使用无参的方式构造对象,也就是当前系统时间
Date(long date)根据参数指定毫秒数构造对象, 参数为距离1970年1月1日0时0分0秒的毫秒数
long getTime()获取调用对象距离1970年1月1日0时0分0秒的毫秒数
void setTime(long time)设置调用对象为距离基准时间time毫秒的时间点
SimpleDateFormat类的概述
(1)基本概念
  • java.text.SimpleDateFormat类主要用于实现日期和文本之间的转换
(2)常用的方法
方法声明功能介绍
SimpleDateFormat()使用无参方式构造对象
SimpleDateFormat(String pattern)根据参数指定的模式来构造对象,模式主要有: y-年 M-月 d-日H-时 m-分 s-秒
final String format(Date date)用于将日期类型转换为文本类型
Date parse(String source)用于将文本类型转换为日期类型
Calendar类的概述
(1)基本概念
  • java.util.Calender类主要用于描述特定的瞬间取代Date类中的过时方法实现全球化
  • 该类是个抽象类,因此不能实例化对象,其具体子类针对不同国家的日历系统,其中应用广泛是GregorianCalendar(格里高利历)对应世界上绝大多数国家/地区使用的标准日历系统
(2)常用的方法
方法声明功能介绍
static Calendar getInstance()用于获取Calendar类型的引用
void set(int year, int month, int date, int hourOfDay, int minute, int second)用于设置年月日时分秒信息
Date getTime()用于将Calendar类型转换为 Date类型
void set(int field, int value)设置指定字段的数值
void add(int field, int amount)向指定字段增加数值
(3)多态的使用场合
  • 通过方法的参数传递形成多态;
public static void draw(Shape s){
    s.show();
}
draw(new Rect(1, 2, 3, 4));
  • 在方法体中直接使用多态的语法格式
Account acc = new FixedAccount();
  • 通过方法的返回值类型形成多态
Calender getInstance(){
	return new GregorianCalendar(zone, aLocale);
}
笔试考点
  • 既然Calendar是个抽象类不能创建对象,那么下面的方法为啥可以获取Calendar类型的引用呢?
// 解析:由源码可知,返回的并不是Calendar类型的对象,
// 而是Calendar类的子类GregorianCalendar等对象,形成了多态
// 多态的使用场合之三
Calendar instance = Calendar.getInstance();

第三节:Java8中的日期相关类(熟悉

Java8日期类的由来
  • JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少它们面临的问题是:

    Date类中的年份是从1900开始的,而月份都从0开始

    格式化只对Date类有用,对Calendar类则不能使用

    非线程安全等。

Java8日期类的概述
  • Java 8通过发布新的Date-Time API进一步加强对日期与时间的处理
  • java.time包:该包日期/时间API的基础包
  • java.time.chrono包:该包提供对不同日历系统的访问
  • java.time.format包:该包能够格式化和解析日期时间对象
  • java.time.temporal包:该包包含底层框架和扩展特性
  • java.time.zone包:该包支持不同时区以及相关规则的类
LocalDate类的概述
(1)基本概念
  • java.time.LocalDate类主要用于描述年-月-日格式的日期信息,该类不表示时间和时区信息
(2)常用的方法
方法声明功能介绍
static LocalDate now()在默认时区中从系统时钟获取当前日期
LocalTime类的概述
(1)基本概念
  • java.time.LocalTime类主要用于描述时间信息,可以描述时分秒以及纳秒
(2)常用的方法
方法声明功能介绍
static LocalTime now()从默认时区的系统时间中获取当前时间
static LocalTime now(ZoneId zone)获取指定时区的当前时间
LocalDateTime类的概述
(1)基本概念
  • java.time.LocalDateTime类主要用于描述ISO-8601日历系统中没有时区的日期时间,如2007-1203T10:15:30。
(2)常用的方法
方法声明功能介绍
static LocalDateTime now()从默认时区的系统时间中获取当前日期时间
static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second)根据参数指定的年月日时分秒信息来设置日期时间
int getYear()获取年份字段的数值
int getMonthValue()获取1到12之间的月份字段
int getDayOfMonth()获取日期字段
int getHour()获取小时数
int getMinute()获取分钟数
int getSecond()获取秒数
LocalDateTime withYear(int year)设置为参数指定的年
LocalDateTime withMonth(int month)设置为参数指定的月
LocalDateTime withDayOfMonth(int dayOfMonth)设置为参数指定的日
LocalDateTime withHour(int hour)设置为参数指定的时
LocalDateTime withMinute(int minute)设置为参数指定的分
LocalDateTime withSecond(int second)设置为参数指定的秒
LocalDateTime plusYears(long years)加上参数指定的年
LocalDateTime plusMonths(long months)加上参数指定的月
LocalDateTime plusDays(long days)加上参数指定的日
LocalDateTime plusHours(long hours)加上参数指定的时
LocalDateTime plusMinutes(long minutes)加上参数指定的分
LocalDateTime plusSeconds(long seconds)加上参数指定的秒
LocalDateTime minusYears(long years)减去参数指定的年
LocalDateTime minusMonths(long months)减去参数指定的月
LocalDateTime minusDays(long days)减去参数指定的日
LocalDateTime minusHours(long hours)减去参数指定的时
LocalDateTime minusMinutes(long minutes)减去参数指定的分
LocalDateTime minusSeconds(long seconds)减去参数指定的秒
Instant类的概述
(1)基本概念
  • java.time.Instant类主要用于描述瞬间的时间点信息
(2)常用的方法
方法声明功能介绍
static Instant now()从系统时钟上获取当前时间
OffsetDateTimeatOffset(ZoneOffset offset)将此瞬间与偏移量组合以创建偏移日期时间
static Instant ofEpochMilli(long epochMilli)根据参数指定的毫秒数来构造对象,参数为距离1970年1月1 日0时0分0秒的毫秒数
long toEpochMilli()获取距离1970年1月1日0时0分0秒的毫秒数
DateTimeFormatter类的概述
(1)基本概念
  • java.time.format.DateTimeFormatter类主要用于格式化和解析日期
(2)常用的方法
方法声明功能介绍
static DateTimeFormatter ofPattern(String pattern)根据参数指定的模式来获取对象
String format(TemporalAccessor temporal)将参数指定日期时间转换为字符串
TemporalAccessor parse(CharSequence text)将参数指定字符串转换为日期时间

任务四:集合类库(上)

第一节:集合的概述(重点

集合的由来
  • 当需要在Java程序中记录单个数据内容时,则声明一个变量
  • 当需要在Java程序中记录多个类型相同的数据内容时,声明一个一维数组
  • 当需要在Java程序中记录多个类型不同的数据内容时,则创建一个对象
  • 当需要在Java程序中记录多个类型相同的对象数据时,创建一个对象数组
  • 当需要在Java程序中记录多个类型不同的对象数据时,则准备一个集合
集合的框架结构
  • Java中集合框架顶层框架是:java.util.Collection集合 和 java.util.Map集合。

  • 其中Collection集合存取元素的基本单位是:单个元素

  • 其中Map集合存取元素的基本单位是:单对元素

    01 集合框架的两张图

第二节:Collection集合(重点

基本概念
  • java.util.Collection接口是List接口、Queue 接口以及Set接口的父接口,因此该接口里定义的方法既可用于操作List集合也可用于操作Queue集合和Set集合
常用的方法(练熟、记住
方法声明功能介绍
boolean add(E e)向集合中添加对象
boolean addAll(Collection<? extendsE> c)用于将参数指定集合c中的所有元素添加到当前集合中
boolean contains(Object o)判断是否包含指定对象
boolean containsAll(Collection<?> c)判断是否包含参数指定的所有对象
boolean retainAll(Collection<?> c)保留当前集合中存在且参数集合中存在的所有对象(取交集)
boolean remove(Object o)从集合中删除对象
boolean removeAll(Collection<?> c)从集合中删除参数指定的所有对象
void clear()清空集合
int size()返回包含对象的个数
boolean isEmpty()判断是否为空
boolean equals(Object o)判断是否相等
int hashCode()获取当前集合的哈希码值
Object[] toArray()将集合转换为数组
Iterator iterator()获取当前集合的迭代器
笔试考点
  • 考点一:
Collection c1 = new ArrayList();
c1.add(new String("one"));
c1.add(Integer.valueOf(2));
Collection c2 = new ArrayList();
// 常量池
c2.add("three");
// 自动装箱机制
c2.add(4);
System.out.println("c2 = " + c2);
//[three, 4]
c1.addAll(c2);
///c1.add(c2);
boolean b1 = c1.containsAll(c2);
System.out.println("b1 = " + b1);
//true
///false
// 判断集合c1中是否拥有集合c2这个整体为单位的元素
b1 = c1.contains(c2);
System.out.println("b1 = " + b1);
//false
///true
  • 考点二:
Collection c3 = new ArrayList();
c3.add(4);
//从集合c1中删除集合c3中的所有元素,本质上就是一个一个元素进行删除,有元素则删除,否则不删除
b1 = c1.removeAll(c3);
//笔试考点  删除整体对象c3
b1 = c1.remove(c3);
System.out.println("b1 = " + b1);
//false
System.out.println("c1 = " + c1);
//[2, three]

第三节:Iterator接口(重点

基本概念
  • java.util.Iterator接口主要用于描述迭代器对象,可以遍历Collection集合中的所有元素
  • java.util.Collection接口继承Iterator接口,因此所有实现Collection接口的实现类都可以使用该迭代器对象
常用的方法
方法声明功能介绍
boolean hasNext()判断集合中是否有可以迭代/访问的元素
E next()用于取出一个元素并指向下一个元素
void remove()用于删除访问到的最后一个元素
  • 案例题目:

    如何使用迭代器实现toString方法的打印效果?

// 1.准备一个Collection集合并放入元素后打印
Collection c1 = new ArrayList();
c1.add("one");
c1.add(2);
c1.add(new Person("Saber", 30));
// 2.使用迭代器来遍历集合中的所有元素  更加灵活
// 2.1 获取当前集合中的迭代器对象
Iterator iterator1 = c1.iterator();
// 3.使用迭代器来模拟toString方法的打印效果
StringBuilder sb1 = new StringBuilder();
sb1.append("[");
while (iterator1.hasNext()) {
    Object obj = iterator1.next();
    // 当获取的元素是最后一个元素时,则拼接元素加中括号
    if (!iterator1.hasNext()) {
        sb1.append(obj).append("]");
    } else {
        // 否则拼接元素加逗号加空格
        sb1.append(obj).append(",").append(" ");
    }
}
// [one, 2, Person{name='Saber', age=30}]
System.out.println("c1 = " + sb1);

第四节:for each循环(重点

基本概念
  • Java5推出增强型for循环语句,可以应用数组和集合的遍历
  • 经典迭代的“简化版”
语法格式
  • 伪代码:
for(元素类型 变量名 : 数组/集合名称) {
	循环体;
}
执行流程
  • 不断地从数组/集合中取出一个元素赋值给变量名并执行循环体,直到取完所有元素为止。

第五节:List集合(重中之重

基本概念
  • java.util.List集合是Collection集合的子集合,该集合中允许有重复的元素并且有先后放入次序

  • 该集合的主要实现类有:ArrayList类、LinkedList类、Stack类、Vector类。

  • 其中ArrayList类的底层是采用动态数组进行数据管理的,支持下标访问增删元素不方便

    02 ArrayList类的底层原理

  • 其中LinkedList类的底层是采用双向链表进行数据管理的,访问不方便增删元素方便

    03 LinkedList类的底层原理

  • 可以认为ArrayList和LinkedList的方法在逻辑上完全一样,只是在性能上有一定的差别,ArrayList 更适合于随机访问而LinkedList更适合于插入和删除;在性能要求不是特别苛刻的情形下可以忽略这个差别

  • 其中Stack类的底层是采用动态数组进行数据管理的,该类主要用于描述一种具有后进先出特征的数据结构,叫做(last in first out LIFO)。

    04 栈的特性

  • 其中Vector类的底层是采用动态数组进行数据管理的,该类与ArrayList类相比属于线程安全的类,效率比较低,以后开发中基本不用

常用的方法
方法声明功能介绍
void add(int index, E element)向集合中指定位置添加元素
boolean addAll(int index, Collection<?extends E> c)向集合中添加所有元素
E get(int index)从集合中获取指定位置元素
int indexOf(Object o)查找参数指定的对象
int lastIndexOf(Object o)反向查找参数指定的对象
E set(int index, E element)修改指定位置的元素
E remove(int index)删除指定位置的元素
List subList(int fromIndex, int toIndex)用于获取子List
  • 案例题目

    准备一个Stack集合,将数据11、22、33、44、55依次入栈并打印,然后查看栈顶元素并打印,然后将栈中所有数据依次出栈并打印。

    再准备一个Stack对象,将数据从第一个栈中取出来放入第二个栈中,然后再从第二个栈中取出并打印。

public class StackTest {

    public static void main(String[] args) {

        // 1.准备一个Stack类型的对象并打印
        Stack s1 = new Stack();
        Stack s2 = new Stack();
        System.out.println("s1 = " + s1);
        // [啥也没有]
        System.out.println("s2 = " + s2);
        // [啥也没有]

        System.out.println("-----------------------------------------------");
        // 2.将数据11、22、33、44、55依次入栈并打印
        for (int i = 1; i <= 5; i++) {
            Object obj = s1.push(i * 11);
            System.out.println("入栈的元素是:" + obj);
            System.out.println("栈中的元素有:" + s1);
            // 11 22 33 44 55
        }

        System.out.println("-----------------------------------------------");

        // 3.查看栈顶元素值并打印
        Object obj2 = s1.peek();
        System.out.println("获取到的栈顶元素是:" + obj2);
        // 55

        System.out.println("-----------------------------------------------");
        // 4.对栈中所有元素依次出栈并打印
        int len = s1.size();
        for (int i = 1; i <= len; i++) {
            Object to = s1.pop();
            System.out.println("出栈的元素是:" + to);
            // 55 44 33 22 11
            s2.push(to);
        }

        System.out.println("-----------------------------------------------");

        // 5.最终打印栈中的所有元素
        System.out.println("s1 = " + s1);
        // [啥也没有]

        System.out.println("-----------------------------------------------");

        len = s2.size();
        for (int i = 1; i <= len; i++) {
            Object to = s2.pop();
            System.out.println("出栈的元素是:" + to);
            // 11 22 33 44 55
        }
    }
}

第六节:Queue集合(重点

基本概念
  • java.util.Queue集合是Collection集合的子集合,与List集合属于平级关系

  • 该集合的主要用于描述具有先进先出特征的数据结构,叫做队列(first in first out FIFO)。

  • 该集合的主要实现类是LinkedList类,因为该类在增删方面比较有优势

    05 队列的特性

常用的方法
方法声明功能介绍
boolean offer(E e)将一个对象添加至队尾,若添加成功则返回true
E poll()从队首删除并返回一个元素
E peek()返回队首的元素(但并不删除)
  • 案例题目

    准备一个Queue集合,将数据11、22、33、44、55依次入队并打印,然后查看队首元素并打印,然后将队列中所有数据依次出队并打印。

任务五:集合类库(下)

第一节:泛型机制(熟悉)

基本概念
  • 通常情况下集合中可以存放不同类型的对象,是因为将所有对象都看做Object类型放入的,因此从集合中取出元素时也是Object类型为了表达该元素真实的数据类型,则需要强制类型转换,而强制类型转换可能会引发类型转换异常

  • 为了避免上述错误的发生从Java5开始增加泛型机制,也就是在集合名称的右侧使用<数据类型> 的方式来明确要求该集合中可以存放的元素类型,若放入其它类型的元素则编译报错

  • 泛型只在编译时期有效,在运行时期不区分是什么类型

  • Java7开始的新特性菱形特性即集合泛型就是后面<>中的数据类型可以省略

笔试考点
  • 代码:
// 1.准备一个支持泛型机制的List集合,明确要求集合中的元素是String类型
List<String> lt1 = new LinkedList<String>();
// 2.向集合中添加元素并打印
lt1.add("one");
System.out.println("lt1 = " + lt1); 
// [one]

// Java7开始的新特性: 菱形特性   就是后面<>中的数据类型可以省略
List<Double> lt3 = new LinkedList<>();
// 笔试考点
// 试图将lt1的数值赋值给lt3,也就是覆盖lt3中原来的数值,结果编译报错:集合中支持的类型不同
//lt3 = lt1; Error
底层原理
  • 泛型的本质就是参数化类型,也就是让数据类型作为参数传递,其中E相当于形式参数负责占位,而使用集合时<>中的数据类型相当于实际参数,用于给形式参数E进行初始化,从而使得集合中所有的E被实际参数替换,由于实际参数可以传递各种各样广泛的数据类型,因此得名为泛型
  • 如:
//其中i叫做形式参数,负责占位 							   其中E叫做形式参数,负责占位
//int i = 10; 											E = String;
//int i = 20; 											E = Integer;
public static void show(int i) {						  public interface List<E> {
    ...														...
}													   }
//其中10叫做实际参数,负责给形式参数初始化 					//其中String叫做实际参数
show(10); 												List<String> lt1 = ...;
show(20);												List<Integer> lt2 = ...;
自定义泛型接口
  • 泛型接口和普通接口的区别就是后面添加了类型参数列表可以有多个类型参数,如:<E, T, … > 等。
自定义泛型类
  • 泛型类和普通类的区别就是类名后面添加了类型参数列表可以有多个类型参数,如:<E, T, … > 等。
  • 实例化泛型类时应该指定具体的数据类型,并且是引用数据类型不是基本数据类型
  • 父类有泛型子类可以选择保留泛型也可以选择指定泛型类型
  • 子类必须是“富二代”子类除了指定或保留父类的泛型还可以增加自己的泛型
自定义泛型方法
  • 泛型方法就是我们输入参数的时候,输入的是泛型参数,而不是具体的参数。我们在调用这个泛型方法的时需要对泛型参数进行实例化

  • 泛型方法的格式

[访问权限] <泛型> 返回值类型 方法名([泛型标识 参数名称]) {
    方法体;
}
  • 静态方法中使用泛型参数的时候,需要我们把静态方法定义为泛型方法
泛型在继承上的体现
  • 如果B是A的一个子类或子接口,而G是具有泛型声明的类或接口,则G并不是G的子类型!比如:String是Object的子类,但是List并不是List的子类。
通配符的使用
  • 有时候我们希望传入的类型在一个指定的范围内,此时就可以使用泛型通配符了。

  • 如:之前传入的类型要求为Integer类型,但是后来业务需要Integer的父类Number类也可以传入

  • 泛型中有三种通配符形式:

    <?> 无限制通配符:表示我们可以**传入任意类型的参数**。

    <? extends E> 表示类型的上界是E,只能是E或者是E的子类(即里面所有E或E的子类元素我都可以用E类型来拿/取)。

    <? super E> 表示类型的下界是E,只能是E或者是E的父类(即我可以接收E或E的子类元素)。

第二节:Set集合(熟悉)

基本概念
  • java.util.Set集合是Collection集合的子集合,与List集合平级

    01 集合框架的两张图

  • 该集合中元素没有先后放入次序(不代表随机),且不允许重复

  • 该集合的主要实现类是:HashSet类 和 TreeSet类以及LinkedHashSet类

  • 其中HashSet类的底层是采用哈希表进行数据管理的。

    哈希表的结构:

    02 哈希表的结构

  • 其中TreeSet类的底层是采用红黑树进行数据管理的。

    红黑树的结构:

    06 红黑树

  • 其中LinkedHashSet类与HashSet类的不同之处在于内部维护了一个双向链表链表中记录了元素的迭代顺序也就是元素插入集合中的先后顺序,因此便于迭代

常用的方法
  • 参考Collection集合中的方法即可!

  • 案例题目

    准备一个Set集合指向HashSet对象,向该集合中添加元素"two"并打印,再向集合中添加元素"one"并打印,再向集合中添加元素"three"并打印,再向集合中添加"one"并打印。

public class HashSetTest {

    public static void main(String[] args) {
		// 1.声明一个Set类型的引用指向HashSet类型的对象
        Set<String> s1 = new HashSet<>();
        //Set<String> s1 = new LinkedHashSet<>();
		// 将放入的元素使用双链表连接起来
        System.out.println("s1 = " + s1); 
		// [啥也没有]

        System.out.println("----------------------------------------------------");
        
		// 2.向集合中添加元素并打印
        boolean b1 = s1.add("two");
        System.out.println("b1 = " + b1); 
		// true
        System.out.println("s1 = " + s1); 
		// [two]
        
		// 从打印结果上可以看到元素没有先后放入次序(表面)
        b1 = s1.add("one");
        System.out.println("b1 = " + b1); 
		// true
        System.out.println("s1 = " + s1); 
		// [one, two]  [two, one]

        b1 = s1.add("three");
        System.out.println("b1 = " + b1); 
		// true
        System.out.println("s1 = " + s1); 
		// [one, two, three]  [two, one, three]
		// 验证元素不能重复
        b1 = s1.add("one");
        System.out.println("b1 = " + b1); 
		// false
        System.out.println("s1 = " + s1); 
		// [one, two, three]  [two, one, three]
    }
}
元素放入HashSet集合的原理

03 元素放入哈希表的过程

  • 使用元素调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算出该元素在数组中的索引位置

  • 若该位置没有元素,则将该元素直接放入即可。

  • 若该位置有元素,则使用新元素与已有元素依次比较哈希值若哈希值不相同,则将该元素直接放入

  • 若新元素与已有元素的哈希值相同,则使用新元素调用equals方法与已有元素依次比较

  • 若相等则添加元素失败否则将元素直接放入即可

  • 思考:为什么要求重写equals方法后要重写hashCode方法呢?

  • 解析:

    当两个元素调用equals方法相等时证明这两个元素相同,重写hashCode方法后保证这两个元素得到的哈希码值相同,由同一个哈希算法生成的索引位置相同,此时只需要与该索引位置已有元素比较即可,从而提高效率并避免重复元素的出现

TreeSet集合的概念
  • 二叉树主要指每个节点最多只有两个子节点的树形结构

    04 二叉树的基本概念

  • 满足以下3个特征的二叉树叫做有序二叉树:

    a**.左子树中的任意节点元素都小于根节点元素值**;

    b.右子树中的任意节点元素都大于根节点元素值

    c.左子树和右子树的内部也遵守上述规则

    05 有序二叉树的基本概念

  • 由于TreeSet集合的底层采用红黑树(特殊的有序二叉树)进行数据的管理,当有新元素插入到TreeSet集合时,需要使用新元素与集合中已有的元素依次比较来确定新元素的合理位置

  • 比较元素大小的规则有两种方式

    使用元素的自然排序规则进行比较并排序,让元素类型实现java.lang.Comparable接口

    使用比较器规则进行比较并排序构造TreeSet集合时传入java.util.Comparator接口

  • 自然排序的规则比较单一,而比较器的规则比较多元化,而且比较器优先于自然排序

第三节:Map集合(重点)

基本概念
  • java.util.Map<K,V>集合中存取元素的基本单位是:单对元素,其中类型参数如下

    K - 此映射所维护的键(Key)的类型,相当于目录

    V - 映射值(Value)的类型,相当于内容

  • 该集合中key是不允许重复的,而且一个key只能对应一个value

  • 该集合的主要实现类有:HashMap类、TreeMap类、LinkedHashMap类、Hashtable类、Properties类

  • 其中HashMap类的底层是采用哈希表进行数据管理的。

  • 其中TreeMap类的底层是采用红黑树进行数据管理的。

  • 其中LinkedHashMap与HashMap类的不同之处在于内部维护了一个双向链表,链表中记录了元素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代

  • 其中Hashtable类是古老的Map实现类与HashMap类相比属于线程安全的类,且不允许null作为key或者value的数值

  • 其中Properties类是Hashtable类的子类,该对象用于处理属性文件key和value都是String类型的

  • Map集合是面向查询优化的数据结构, 在大数据量情况下有着优良的查询性能

  • 经常用于根据key检索value的业务场景

    Set集合与Map集合的关系

    07 Set集合转换为Map集合的原理

常用的方法
方法声明功能介绍
V put(K key, V value)将Key-Value对存入Map,若集合中已经包含该Key,则替换该Key所对应的Value,返回值为该Key原来所对应的Value,若没有则返回null
V get(Object key)返回与参数Key所对应的Value对象,如果不存在则返回null
boolean containsKey(Object key);判断集合中是否包含指定的Key
boolean containsValue (Object value);判断集合中是否包含指定的Value
V remove(Object key)根据参数指定的key进行删除
Set keySet()返回此映射中包含的键的Set视图
Collection values()返回此映射中包含的值的Set视图
Set<Map.Entry<K,V>> entrySet()返回此映射中包含的映射的Set视图
元素放入HashMap集合的原理

03 元素放入哈希表的过程

  • 使用元素的key调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算在数组中的索引位置

  • 若该位置没有元素,则将该键值对直接放入即可。

  • 若该位置有元素,则使用key与已有元素依次比较哈希值若哈希值不相同,则将该元素直接放入

  • 若key与已有元素的哈希值相同,则使用key调用equals方法与已有元素key依次比较

  • 若相等则将对应的value修改否则将键值对直接放入即可。

相关的常量
  • DEFAULT_INITIAL_CAPACITY :HashMap的默认容量是16。

  • DEFAULT_LOAD_FACTOR:HashMap的默认加载因子是0.75。

  • threshold扩容的临界值,该数值为:容量*填充/加载因子,也就是12。

  • TREEIFY_THRESHOLD:若Bucket中链表长度大于该默认值则转化为红黑树存储(临界值),该数值是8。

  • MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量,该数值是64。

第四节:Collections类

基本概念
  • java.util.Collections类主要提供了对集合操作或者返回集合的静态方法
常用的方法
方法声明功能介绍
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)根据元素的自然顺序返回给定集合的 大元素
static T max(Collection<? extends T> coll, Comparator<? super T> comp)根据指定比较器引发的顺序返回给定集合的 大元素
static <T extends Object & Comparable<?super T>> T min(Collection<? extends T> coll)根据元素的自然顺序返回给定集合的 小元素
static T min(Collection<? extends T> coll, Comparator<? super T> comp)根据指定比较器引发的顺序返回给定集合的 小元素
static void copy(List<? super T> dest, List<? extends T> src)将一个列表中的所有元素复制到另一个列表中
方法声明功能介绍
static void reverse(List<?> list)反转指定列表中元素的顺序
static void shuffle(List<?> list)使用默认的随机源随机置换指定的列表
static <T extends Comparable<? super T>> void sort(List list)根据其元素的自然顺序将指定列表按升序排序
static void sort(List list, Comparator<? super T> c)根据指定比较器指定的顺序对指定列表进行排序
static void swap(List<?> list, int i, int j)交换指定列表中指定位置的元素

总结

任务一

  1. 常用的包(熟悉)

    java.lang. java,util, java.io. java.net. java.sql. …

  2. Object类(重点)

    概念、equals0. hashCode(. toString0、 …

  3. 包装类(熟悉)

    概念、Integer类. Double类、 Boolean类、 Character类、 …

  4. 常用的数学处理类(孰悉)

    Math类、BigDecimal类、 BigInteger类、 …

任务二

  1. String类(重点)

    概念、常量池、常用的构造方法、常用的成员方法、正则表达式的概念和使用、相关的方法等

任务三

  1. 可变字符串类(重点)

    StringBuilder类StringBuffer类 概念和常用方法等

  2. Java8之前的日期相关类(熟悉)

    Date类、Calendar类、 SimpleDateFormat类、 概念和常用方法等

  3. Java8增加的日期相关类(熟悉)

    LocalDate类、LocalTime类、 LocalDateTime类、 Instant类、 Date TimeFormatter类、概念和常用方法等

任务四

  1. 集合的概述

    集合的由来、两张图

  2. Collection集合

    常用的方法

  3. Iterator接口

    概念、遍历集合、常用的方法

  4. for each结构

    是Java5新增的内容,是迭代器的简化版

  5. List集合

    概念、常用实现类、常用的方法

  6. Queue集合

    概念、常用实现类、常用的方法

任务五

  1. 泛型机制(熟悉)

    概念和本质、自定义泛型接口、类、方法,继承方面的体现,通配符

  2. Set集合(熟悉)

    概念、主要实现类、常用的方法、两种方式指定排序的规则

  3. Map集合(重点)

    概念、主要实现类、常用的方法

  4. Collections类(熟悉)

    概念和常用的方法

笔试题

笔试题一

  • 下面代码的输出结果是什么?
String s1 = "abc';
String s2 = new String("abc");
s2.intern();
System.out.println(s1 == s2);
  • false,虽然intern()会返回该字符串对象在常量池中的地址,但并没有用s2接收即并没有覆盖变量s2原来的值。

笔试题二

  • String是线程安全的吗?

    是线程安全的。因为String描述的字符串是常量不可改变即String对象一旦创建其内容就不可改变,多个人访问也不会出现线程安全问题。

笔试题三

  • 为什么在使用HashMap的时候总是使用String类作为key的类型?

    因为String是一个不可变类,一旦创建就不可改变,所以类内部会将计算出来的hash码值缓存起来,而HashMap的key会用到hash码值,String早就给缓存起来了,所以使用String。

笔试题四

  • Collection和Collections类有什么区别?

    看定义,一个集合,一个工具类。

笔试题五

  • HashMap在Java7和Java8有哪些主要不同之处?

    Java7中采用的是链表数组,插入元素用头插法,Java8底层是链表数组加红黑树,当长度达到临界值,自动变红黑树,采用尾插法,hash算法,扩容方式不一样。

Gitee仓库地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值