一、常用的类
(一)、Object类
1、java.lang.Object类是Java语言中类层次结构的根类,也就是说任何一个类都是该类的直接或者间接子类。如果定义一个Java类时没有使用extends关键字声明其父类,则其父类为 java.lang.Object 类。Object类定义了“对象”的基本行为, 被子类默认继承。
2、从Object类中继承下来的equals方法,默认比较的是两个对象的地址值。与 == 运算符的结果一致。 若希望比较两个对象的内容,则需要重写该方法。
3、Object的String toString()方法,用于获取调用对象的字符串形式,该方法默认返回的字符串为:包名.类名@哈希码值的十六进制,为了返回更有意义的数据,需要重写该方法,使用print或println打印引用或字符串拼接引用都会自动调用该方法。
(二)、包装类
1、包装类就是能将java中八种基本数据类型打包成对象,这样就能间接的实现调用。
2、包装类型
包装类 | 对应的基本类型 |
---|---|
java.lang.Byte | byte |
java.lang.Short | short |
java.lang.Integer | int |
java.lang.Long | long |
java.lang.Float | float |
java.lang.Double | double |
java.lang.Boolean | boolean |
java.lang.Character | char |
(三)、Integer类
1、Integer是int类型的包装类,Integer里面重写了equals方法。常用的方法有:
intValue() 获取调用对象中的整数值并返回
根据参数指定整数值得到Integer类型对象:Integer num = Integer.ValueOf(123);
2、自动装箱和拆箱的概念
(1)自动装箱:从int类型到Integer类型的转换,这个打包的过程叫做自动装箱。从java开始,出现了自动拆装箱,例:Integer num = 5;
(2)自动拆箱:从Integer类型到int类型的转换,这个过程叫做自动拆箱。例:int it = 100;
3、自动装箱池
在Integer类的内部提供了自动装箱池技术,将-128到127之间的整数已经装箱完毕,当程序中使用该范围之间的整数时,无需装箱直接取用自动装箱池中的对象即可,从而提高效率。
(四)、Math类
1、java.lang.Math类主要用于提供执行数学运算的方法,如:对数,平方根。可以用类名.的方式直接调用。
public calss MathTest{
public static void main(String[] args){
System.out.println("获取两个整数中的最大值"+Math.max(10,20));
System.out.println("获取次方"+Math.pow(2,3));
System.out.println("获取绝对值"+Math.abs(-5));
System.out.println("获取四舍五入值"+Math.round(3.14));
System.out.println("获取随机数"+Math.random());
}
}
(四)、BigDecimal类
1、由于float类型和double类型在运算时可能会有误差,若希望实现精确运算则借助java.math.BigDecimal类型加以描述。
public calss BigDecimalTest{
public static void main(String[] args){
BigDecimal num1= new BigDecimal("1.2");
BigDecimal num2= new BigDecimal("1.4");
System.out.println("实现加法运算"+num1.add(num2)); //2.6
System.out.println("实现减法运算"+num2.subtract(num1));
System.out.println("实现乘法运算"+num2.multiply(num1));
System.out.println("实现除法运算"+num2.divide(num1));
System.out.println("==============================");
System.out.println("直接运算结果"+1.2+1.4); //0.3000000000004
}
}
(五)、 BigInteger类
1、若希望表示比long类型范围还大的整数数据,则需要借助java.math.BigInteger类型描述。
public calss BigIntegerTest{
public static void main(String[] args){
BigInteger num1= new BigInteger("20");
BigInteger num2= new BigInteger("8");
System.out.println("实现加法运算"+num1.add(num2)); //28
System.out.println("实现减法运算"+num2.subtract(num1));
System.out.println("实现乘法运算"+num2.multiply(num1));
System.out.println("实现除法运算"+num2.divide(num1));
System.out.println("实现求余数运算"+num2.remainder(num1));
}
}
二、String类
(一)、 String类的概念
1、java.lang.String类用于描述字符串,Java程序中所有的字符串字面值都可以使用该类的对象加以描述,如:“abc”。该类由final关键字修饰,表示该类不能被继承。该类描述的字符串内容是个常量不可更改,因此可以被共享使用。
如:
String str1 = “abc”; - 其中"abc"这个字符串是个常量不可改变。
str1 = “123”; - 将“123”字符串的地址赋值给变量str1。
- 改变str1的指向并没有改变指向的内容
2、常量池
由于String类型描述的字符串内容是常量不可改变,因此Java虚拟机将首次出现的字符串放入常量池中,若后续代码中出现了相同字符串内容则直接使用池中已有的字符串对象而无需申请内存及创建对象,从而提高了性能。
(二)、 String类初始化
1、通过直接赋值的方式可以初始化。
2、通过构造方法进行初始化。根据参数指定的字符串内容来构造对象,新创建对象为参数对象的副本,
public calss StringTest{
public static void main(String[] args){
//方式一:会创建一个对象,存放在常量池中
String str1 = "hello"; //常量池中
String str2 = "hello"; //常量池中
//方式二:会创建两个对象,一个对象存放在常量池中,一个在堆区
String str3 = new String("hello"); //堆区中
String str4 = new String("hello"); //堆区中
//true 比较的是地址,都在常量池中
System.out.println(str1 == str2);
//true 比较的是内容,指向常量池中的同一个值
System.out.println(str1.equals(str2));
//false 比较的是地址,堆区的地址不一样
System.out.println(str3 == str4);
//true 比较的是内容
System.out.println(str3.equals(str4));
//false 比较的是地址,一个指向常量池一个指向堆区
System.out.println(str2 == str4);
//true 比较的是内容
System.out.println(str2.equals(str4));
System.out.println("====================");
String str5 = "abcd";
String str6 = "ab" + "cd";
//true 比较的是地址,常量优化,str6拼接之后值为abcd在常量池中有值
System.out.println(str5 == str6);
String str7 = "abcd";
String str8 = str7 + "cd";
//false 比较的是地址,变量拼接不满足常量优化,是一个新的对象
System.out.println(str7 == str8);
}
}
(三)、 String类常用的成员方法
1、String类型和数组之间的转换
public calss StringByteCharTest{
public static void main(String[] args){
String str1 = new String("word");
System.out.println(str1); //word 会自动调用toString()方法
//String类型转换为byte数组类型
byte[] bArr = str1.getBytes();
//将byte数组转回String类型 ---用构造方法
String str2 = new String(bArr);
//String类型转换为char数组类型
char[] cArr = str1.toCharArray();
//将char数组转回String类型 ---用构造方法
String str3 = new String(cArr);
}
}
2 、String类中字符的获取和使用
public calss StringCharTest{
public static void main(String[] args){
String str1 = new String("hello");
System.out.println(str1); //word 会自动调用toString()方法
System.out.println(str1.length()); //5 获取字符串的长度在
System.out.println(str1.charAt(0));// h 获取字符串指定位置的字符
System.out.println(str1.isEmpty()?"为空":"不为空");
}
}
3、String类实现字符串之间比较大小——str1.compareTo()
public calss StringComparTest{
public static void main(String[] args){
String str1 = new String("hello");
System.out.println(str1.compareTo("word")); //用‘h’ 和‘w’比较
}
}
4、字符串拼接以及转换
public calss StringMutiTest{
public static void main(String[] args){
String str1 = new String(" hello word");
//是否包含,这里区分大小写
boolean flag = str1.contains("hello"); //true
//转换为大写
String str2 = str1.toUpperCase();
//转换为小写
String str3 = str1.toLowerCase();
//去掉前导和后继空白的字符串
String str4 = str1.trim(); //hello word
//判断字符串以什么结尾或者开头
String str5 = str1.startsWith("hello"); //false
String str6 = str1.endsWith("word"); //true
String str7 = str1.startsWith("hello",3); //true
}
}
5、比较字符串
String重写了equals方法,equals(Object anObject) 用于比较字符串内容是否相等并返回,equalsIgnoreCase(String anotherString) 用于比较字符串内容是否相等并返回,不考虑大小写,如:'A’和’a’是相等。
6、字符串的查找
public calss StringFindTest{
public static void main(String[] args){
String str1 = new String("hello word");
//在字符串中检索p返回其第一次出现的位置,若找不到返回-1
int pos = str1.indexOf("p"); //-1
//转换为大写
int pos1 = str1.lastIndexOf("d");
}
}
7、字符串中子字符串的获取
public calss StringSubStrTest{
public static void main(String[] args){
String str1 = new String("hello word");
String str2 = str1.substring(6); //word
//指定位置截取,表示可以取到6位置的值,但是不能取到8位置的值
String str3 = str1.substring(6,8); //wo
}
}
8、字符串中切割
public calss StringSplitTest{
public static void main(String[] args){
String str1 = "hello,word";
//以逗号切割字符串
String[] strArr = str1.split(",");
String str2 = "我爱学习";
//将字符串中的我替换为你
String str3 = str2.replace("我","你");
}
}
三、正则表达式
(一)、正则表达式的概念
正则表达式本质就是一个“规则字符串”,可以用于对字符串数据的格式进行验证,以及匹配、查找、替换等操作。该字符串通常使用^运算符作为开头标志,使用$运算符作为结尾标志,当然也可以省略。
(二)、正则表达式的规则
正则表达式 | 说明 |
---|---|
[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次 |
public calss StringRegTest{
public static void main(String[] args){
//输入的字符串
String inputStr = "123456";
//银行卡密码的规则:要求是由6位数字组成。
String strReg = "^[0-9]{6}$";
//String strReg = "^\\d{6}$";
if(inputStr.mathes(strReg)){
System.out.println("输入格式不合法");
}
}
}
三、可变字符串类
(一)、可变字符串
1、由于String类描述的字符串内容是个常量不可改变,当需要在Java代码中描述大量类似的字符串时,只能单独申请和存储,此时会造成内存空间的浪费。
为了解决上述问题,可以使用java.lang.StringBuilder类和java.lang.StringBuffer类来描述字符序列可以改变的字符串,如:“ab”。
StringBuffer类是从jdk1.0开始存在,属于线程安全的类,因此效率比较低。
StringBuilder类是从jdk1.5开始存在,属于非线程安全的类,效率比较高。
(二)、StringBuilder类
1、StringBuilder类的构造方法
方法声明 | 功能介绍 |
---|---|
StringBuilder() | 使用无参方式构造对象,容量为16 |
StringBuilder(int capacity) | 根据参数指定的容量来构造对象,容量为参数指定大小 |
StringBuilder(String str) | 根据参数指定的字符串来构造对象,容量为:16+字符串长度 |
2、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() | 字符串反转 |
public calss StringBuilderTest{
public static void main(String[] args){
//根据参数指定的字符串来构造对象
StringBuilder sb = new StringBuilder("hello");
System.out.println("容量为"+sb.capacity()) //16+5
//插入数据
StringBuilder sb1 = sb.insert(0,"abcd");
//返回值和调用对象是同一个字符串,只写对象会自动调toString()
System.out.println("sb1="+sb1) //abcdhelllo
System.out.println("sb="+sb) //abcdhelllo
//末尾追加字符串
sb1.append("efg"); //abcdhellloefg
//替换
sb1.replace(1,3,"12"); //a12dhellloefg
//反转
sb1.reverce(); //gfeollehd21a
}
}
3、自动扩容机制
当字符串的长度超过了字符串对象的初始容量时,该字符串对象会自动扩容。默认扩容算法是:原始容量*2+2。
4、总结
(1)StringBuilder的成员方法都有返回值,目的是为了实现连续调用的需求。
(2)StringBuilder转换为String类型用toString()方法,String 转换为StringBuilder类型用有参构造方法。
(3)效率比较:StringBuilder>StringBuffer>String
(三)、日期相关类
1、Java.lang.System类中提供的方法:long timeTest = System.currentTimeMillis() //得到毫秒数。
2、java.util.Date类可以获取年月日时分秒,可以精确到毫秒
3、java.text.SimpleDateFormat类主要用于实现日期和文本之间的转换。
public calss DateTest{
public static void main(String[] args){
Date date = new Date();
System.out.println(date) ;
//定义转换格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//日期类型转换为文本类型
String dateStr = sdf.format(date);
//将文本类型转换为日期类型
Date chageDate = sdf.parse(dateStr);
}
}
4、java.util.Calender类主要用于描述特定的瞬间,取代Date类中的过时方法。该类是个抽象类,因此不能实例化对象,其具体子类针对不同国家的日历系统,其中应用最广泛的是GregorianCalendar(格里高利历),对应世界上绝大多数国家/地区使用的标准日历系统。
public calss CalenderTest{
public static void main(String[] args){
//定义转换格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//获取Calendar的引用
Calendar instance = Calendar.getInstance();
//设置指定的时间,月份需要减一,因为月份是从0开始的
instance.set(2010,12-1,1,13,14,2);
Date dateTime = instance.getTime();
String dateTime = sdf.formate(dateTime);
}
}
5、从java1.8开始以后新增了很多关于时间的api处理包,java.time.LocalDate类主要用于描述年-月-日格式的日期信息,该类不表示时间和时区信息。
java.time.LocalTime 类主要用于描述时间信息,可以描述时分秒以及纳秒。
java.time.LocalDateTime类主要用于描述ISO-8601日历系统中没有时区的日期时间,如2007-12-03T10:15:30。
public calss LocalDateTest{
public static void main(String[] args){
//获取当前日期
LocalDate nowTime = LocalDate.now();
//获取当前时间
LocalTime nowTime1 = LocalTime.now();
//获取当前日期和时间
LocalDateTime nowTime2 = LocalDateTime.now();
//使用参数指定年月日时分秒信息并获取
LocalDateTime ofTime =LocalDateTime.of(2010,12-1,1,13,14,2);
System.out.println("年"+ofTime.getYear());
System.out.println("月"+ofTime.getMonthValue());
System.out.println("日"+ofTime. getDayOfMonth());
System.out.println("时"+ofTime.getHour());
System.out.println("分"+ofTime.getMinute());
System.out.println("秒"+ofTime.getSecond());
}
}
6、java.time.Instant类主要用于描述瞬间的时间点信息
public calss InstantTest{
public static void main(String[] args){
//获取当前日期,并不是当前系统的默认时区,我们在东八区,此方法获取的是本初子午线的时间,差8个小时
Instant nowTime = Instant.now();
//加上8小时后获取东八区的时间点
OffsetDateTime offTime = nowTime.atOffset(8);
System.out.println("年"+ofTime.getYear());
System.out.println("月"+ofTime.getMonthValue());
}
}
7、java.time.format.DateTimeFormatter类主要用于格式化和解析日期。
public calss DateTimeFormatterTest{
public static void main(String[] args){
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime) ;
//定义转换格式
DateTimeFormatter sdf = DateTimeFormatter.dateTime ("yyyy-MM-dd HH:mm:ss");
//日期类型转换为文本类型
String dateStr = sdf.format(dateTime);
//将文本类型转换为日期类型
TemporalAccessor chageDate = sdf.parse(dateStr);
}
}
四、collection集合
(一)、collection集合
1、java.util.Collection接口是List接口、Queue 接口以及Set接口的父接口,因此该接口里定义的方法既可用于操作List集合,也可用于操作Queue集合和Set集合。
2、常用的方法
方法声明 | 功能介绍 |
---|---|
boolean add(E e); | 向集合中添加对象 |
boolean addAll(Collection<? extends E>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() | 获取当前集合的迭代器 |
public calss CollectionTest{
public static void main(String[] args){
//Collection是一个抽象接口,不能直接new一个对象
//接口类型的引用指向实现类的对象
Collection c = new ArrayList();
c.add(1);
c.add("two");
//调用ArrayList中的tString()方法
System.out.println(c);
Collection c1 = new ArrayList();
c1.add("one");
//将c1中的元素全部添加到c集合中,并且是一个一个添加
c.addAll(c1); //[1,two,one]
//将集合c1当作一个整体元素添加集合c中
//c.add(c1); //[1,two,[one]]
//判断是否包含指定对象
boolean flag = c.contains("one"); //true
//计算两个集合的交集
Collection c2 = new ArrayList();
Collection c3 = new ArrayList();
c2.add(1);
c2.add(5);
c3.add(1);
c3.add(9);
//取交集,并把结果保留到c2中,若是计算结果发生了改变则返回true
flag = c2.retainAll(c3); //true
//删除操作
flag = c3.remove(1); //true
//集合转换为数组
Object[] objects = c2.toArray();
//数组转换为集合
Collection c5 = Arrays.asList(objects);
}
}
3、contains的工作原理:Objects.equals(o,e),其中o代表contains方法中的形参,e代表集合中的每一个元素,它的工作原理就是拿着参数对象与集合中的已有的元素依次进行比较,比较的方式调用Objects中的equals方法,比较的有两种方法:比较地址,第二种是对象不为空,对象调用equals方法与集合中已有元素相等。即若对象类中没有重写equals方法,则比较的是地址,若是重写了则比较的是内容。
(二)、 Iterator接口
1、java.util.Iterator接口主要用于描述迭代器对象,可以遍历Collection集合中的所有元素。
java.util.Collection接口继承Iterator接口,因此所有实现Collection接口的实现类都可以使用该迭代器对象。
2、
public calss IteratorTest{
public static void main(String[] args){
Collection c = new ArrayList();
c.add(1);
c.add("two");
c.add(new Person("lisi",23));
//使用迭代器遍历,获取迭代器对象
Iterator iterator = c.iterator();
//判断是否有元素返回
while(iterator.hasNext()){
//取出一个元素并指向下一个
iterator.next();
iterator.remove();
//下面的删除方法会发生并发异常,
//在迭代的过程中不能使用集合的删除方法
//c.remove(iterator.next());
}
}
}
(三)、for each循环
增强型for循环语句,可以应用数组和集合的遍历。是经典迭代的“简化版”。
语法格式:for(元素类型 变量名 : 数组/集合名称) {
循环体;
}
public calss ForEachTest{
public static void main(String[] args){
Collection c = new ArrayList();
c.add(1);
c.add("two");
c.add(new Person("lisi",23));
for(Object object : c){
System.out,println("取出来的元素是"+object );
}
}
}
(四)、List集合
1、java.util.List集合是Collection集合的子集合,该集合中允许有重复的元素并且有先后放入次序。该集合的主要实现类有:ArrayList类、LinkedList类、Stack类、Vector类。
- **ArrayList类的底层是采用动态数组进行数据管理的,支持下标访问,增删元素不方便。**扩容长度为原始长度的1.5倍。
- LinkedList类的底层是采用双向链表进行数据管理的,访问不方便,增删元素方便。
- 可以认为ArrayList和LinkedList的方法在逻辑上完全一样,只是在性能上有一定的差别,ArrayList更适合于随机访问而LinkedList更适合于插入和删除;在性能要求不是特别苛刻的情形下可以忽略这个差别。
- 其中Stack类的底层是采用动态数组进行数据管理的,该类主要用于描述一种具有后进先出特征的数据结构,叫做栈(last in first out LIFO)。
- 其中Vector类的底层是采用动态数组进行数据管理的,该类与ArrayList类相比属于线程安全的类,效率比较低,以后开发中基本不用。
2、常用的方法
方法声明 | 功能介绍 |
---|---|
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 |
3、泛型
(1)通常情况下集合中可以存放不同类型的对象,是因为将所有对象都看做Object类型放入的,因此从集合中取出元素时也是Object类型,为了表达该元素真实的数据类型,则需要强制类型转换,而强制类型转换可能会引发类型转换异常。
为了避免上述错误的发生,从Java5开始增加泛型机制,也就是在集合名称的右侧使用<数据类型>的方式来明确要求该集合中可以存放的元素类型,若放入其它类型的元素则编译报错。泛型只在编译时期有效,在运行时期不区分是什么类型。
(2)java7开始,菱形特性:就是后面<>中的数据类型可以省略。
(五)、 Set集合
1、java.util.Set集合是Collection集合的子集合,与List集合平级。
- Set集合中元素没有先后放入次序,且不允许重复。
- Set集合的主要实现类是:HashSet类 和 TreeSet类以及LinkedHashSet类。
- HashSet类的底层是采用哈希表进行数据管理的。元素的顺序与放入顺序无关,它的底层是HashMap。
- TreeSet类的底层是采用红黑树进行数据管理的。
- LinkedHashSet类与HashSet类的不同之处在于内部维护了一个双向链表,链表中记录了元素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代。
public calss HashSetTest{
public static void main(String[] args){
Set<String> s1 = new HashSet<>();
boolean flag = s1.add("one"); //true
flag = s1.add("two"); //true
flag = s1.add("one"); //false 不能添加重复的元素
}
}
2、HashSet集合的原理
(1)存放元素时,元素调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算出该元素在数组中的索引位置。
(2)若该位置没有元素,则将该元素直接放入即可。
(3)若该位置有元素,则使用新元素与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放入。
(4)若新元素与已有元素的哈希值相同,则使用新元素调用equals方法与已有元素依次比较。
(5)若相等则添加元素失败,否则将元素直接放入即可。
3、TreeSet集合
(1)二叉树
(2)有序二叉树,左小于根小于右,整个左小于右,小于根
a.左子树中的任意节点元素都小于根节点元素值;
b.右子树中的任意节点元素都大于根节点元素值;
c.左子树和右子树的内部也遵守上述规则;
(3)红黑树
红黑树是一种特殊的有序二叉树。当有新元素插入到TreeSet集合时,需要使
用新元素与集合中已有的元素依次比较来确定新元素的合理位置。
比较元素大小的规则有两种方式:
使用元素的自然排序规则进行比较并排序,让元素类型实现java.lang.Comparable接口;
使用比较器规则进行比较并排序,构造TreeSet集合时传入java.util.Comparator接口;
TreeSet有大小次序默认从小到大排序。String默认实现了Comparable接口
(六)、 Map集合
1、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的业务场景。
2、常用的方法
方法声明 | 功能介绍 |
---|---|
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视图 |
3、 HashMap的原理
(1)使用元素的key调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算在数组中的索引位置。
(2)若该位置没有元素,则将该键值对直接放入即可。
(3)若该位置有元素,则使用key与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放入。
(4)若key与已有元素的哈希值相同,则使用key调用equals方法与已有元素依次比较。
(5)若相等则将对应的value修改,否则将键值对直接放入即可。
4、相关常量
DEFAULT_INITIAL_CAPACITY : HashMap的默认容量是16。
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子是0.75。
threshold:扩容的临界值,该数值为:容量*填充因子,也就是12。
TREEIFY_THRESHOLD:若Bucket中链表长度大于该默认值则转化为红黑树存储,该数值是8。
MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量,该数值是64。