1.常用类
-
包装类
1.1 包装类是针对八种基本数据类型相对应的引用类型
基本数据类型 | 包装类 |
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
其中后六个类继承了Number类
1.2 包装类和基本数据的转换
装箱:基本类型->包装类型
拆箱:包装类型->基本类型
jdk5及以后是自动装箱和拆箱的,自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
//自动装箱举例
//这里可以把int类型的n赋值给integer,底层会自动装箱
int n = 1;
Integer integer = n;
1.3 包装类和Sring类型的转换
//包装类(Integer)->String
Integer i = 100;//自动装箱
//方式 1
String str1 = i + "";
//方式 2
String str2 = i.toString();
//方式 3
String str3 = String.valueOf(i);
//String -> 包装类(Integer)
String str4 = "12345";
Integer i2 = Integer.parseInt(str4);//使用到自动装箱
Integer i3 = new Integer(str4);//构造器
System.out.println("ok~~");
1.4 Character 类的常用方法
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'));//转成小写
2. Strin类
理解
String 对象用于保存字符串,也就是一组字符序列
字符串常量对象是用双引号括起的字符序列
字符串的字符使用Unicode字符编码,一个字符占两个字节(不区分中英文)
String类实现了 Serializable接口(可串行化,即可以在网络传输)、Comparable接口(对象可以比较大小)
String s = "tom";// 直接赋值
String s2 = new String("tom"); // 调用构造器
两种方式的区别:
方式一(直接赋值):先从常量池查看是否有“tom”数据空间,如果有,直接指向(即一个tom空间可以被多个引用指向);如果没有,则重新创建,然后指向。s最终指向的常量池的空间地址
方式二(调用构造器):先从堆中创建空间,里面有一个value属性(上面提到过),指向常量池里的tom空间。如果常量池没有tom,则重新创建,如果有,直接通过value指向。.s2最终指向的是堆中的空间地址(即value)
String类常用方法
package com.base.javaleson;
public class Demo {
public class StringMethod01 {
public static void main(String[] args) {
String str1 = "hello";
String str2 = "Hello";
System.out.println(str1.equals(str2));
// equalsIgnoreCase 忽略大小写的判断内容是否相等
String username = "johN";
if ("john".equalsIgnoreCase(username)) {
System.out.println("Success!");
} else {
System.out.println("Failure!");
}
// length 获取字符的个数,字符串的长度
System.out.println("abc".length());
// indexOf 获取字符在字符串对象中第一次出现的索引,索引从 0 开始,如果找不到,返回-1
String s1 = "wer@terwe@g";
int index = s1.indexOf('@');
System.out.println(index);// 3
System.out.println("weIndex=" + s1.indexOf("we"));//0
// lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从 0 开始,如果找不到,返回-1
s1 = "wer@terwe@g@";
index = s1.lastIndexOf('@');
System.out.println(index);//11
System.out.println("ter 的位置=" + s1.lastIndexOf("ter"));//4
// substring 截取指定范围的子串
String name = "hello,张三";
// 下面 name.substring(6) 从索引 6 开始截取后面所有的内容
System.out.println(name.substring(6));//截取后面的字符
name.substring(0,5);//表示从索引 0 开始截取,截取到索引 5-1=4 位置
System.out.println(name.substring(2,5));//llo
}
}
}
3. StringBuffer类
StringBuffer基本介绍
StringBuffer代表可变的字符序列,可以对字符串内容进行增删,很多方法与String相同,但StringBuffer是可变长度的。
StringBuffer的直接父类是AbstractStringBuilder,在AbstractStringBuilder中,有属性char [] value,但不是final的,这个value数组是存放字符串内容的,所以是存在堆中的(对比String是的value是指向方法区的常量池中的)。因此StringBuffer字符内容是存在 char [] value 中的,所有变化操作不用每次都更换地址(即不是每次创建对象时),所以效率高于String
String VS StringBuffer
(1)String保存的是字符串常量,里面的值不能修改,每次String类的更新实际上就是更改地址,效率低
(2)StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率高 //这个放在堆中
String 和 StringBuffer 相互转换
package com.base.javaleson;
public class Demo {
public static void main(String[] args) {
//String ->StringBuffer
String str = "hello tom";
//方式 1 使用构造器
StringBuffer stringBuffer = new StringBuffer(str);
//方式 2 使用的是 append 方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str);
//StringBuffer ->String
StringBuffer stringBuffer3 = new StringBuffer("tom");
//方式 1 使用 StringBuffer 提供的 toString 方法
String s = stringBuffer3.toString();
//方式 2: 使用构造器来搞定
String s1 = new String(stringBuffer3);
}
}
StringBuffer 常用方法
package com.base.javaleson;
public class Demo {
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"
// 删删除 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"
// 查找指定的子串在字符串第一次出现的索引,如果找不到返回-1
int 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());//22
System.out.println(s);
}
}
3. StringBuilder类
StringBuilder基本介绍
- 一个可变的字符序列,功能跟StringBuffer一致,但不保证同步(StringBuilder 不是线程安全),但他比StringBuffer要快
- 在StringBuilder上的主要操作就是append和insert方法,可以重载这些方法,以接受任意类型的数据
String、StringBuffer 和 StringBuilder 的比较
StringBuilder和StringBuffer非常相似,都代表可变的字符序列,且方法也一样
String:不可变字符序列,效率低,但是复用效率高
StringBuffer:可变字符序列,效率高(增删)、线程安全
StringBuilder:可变字符序列,效率最高,线程不安全
在对字符串做大量修改时,不要使用String
4. Math类
常用方法:
package com.base.javaleson;
public class Demo01 {
public static void main(String[] args) {
// 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 返回的是 a <= x < b 之间的一个随机小数
// 公式就是 (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);
}
}
4. Arrays类
toString返回数组字符串形式
Integer[] integers = {1, 20, 90};
//直接使用Arrays.toString方法,显示数组
System.out.println(Arrays.toString(integers));
sort排序(自然排序和定制排序)
定制排序可以根据具体需求重写compare方法
Integer arr[] = {1, -1, 7, 0, 89};
Arrays.sort(arr); // 默认排序方法 顺序排序
System.out.println("===默认排序===");
System.out.println(Arrays.toString(arr));
//定制排序
Arrays.sort(arr, new Comparator() {
@Override
public 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]
===定制排序===
[89, 7, 1, 0, -1]
*/
binarySearch通过二分搜索法进行查找。必须是顺序
Integer[] arr = {1, 2, 90, 123, 567};
// binarySearch 通过二分搜索法进行查找,要求必须排好
//1. 使用 binarySearch 二叉查找
//2. 要求该数组是有序的. 如果该数组是无序的,不能使用binarySearch
//3. 如果数组中不存在该元素,就返回 return -(low + 1); 就是负的本来应该在的位置// key not found.
int index = Arrays.binarySearch(arr, 567);// 4
copyOf数组元素的复制
Integer[] newArr = Arrays.copyOf(arr, arr.length);
fill数组元素的填充
Integer[] num = new Integer[]{9,3,2};
//使用 99 去填充 num数组,可以理解成是替换所有原有的元素
Arrays.fill(num, 99);
System.out.println("==num数组填充后==");
System.out.println(Arrays.toString(num));//[99, 99, 99]
equals 比较两个数组元素内容是否完全一致
boolean equals = Arrays.equals(arr, arr2);
asList将一组值,转换成List
List asList = Arrays.asList(2,3,4,5,6,1);//asList方法,会将 (2,3,4,5,6,1)数据转成一个List集合
System.out.println("asList=" + asList);//asList=[2, 3, 4, 5, 6, 1]
System.out.println("asList的运行类型" + asList.getClass());//asList的运行类型class java.util.Arrays$ArrayList
5.System类
1. exit(0) //退出当前程序,0代表正常状态
2. 复制数组元素
//arraycopy :复制数组元素,比较适合底层调用,
// 一般使用Arrays.copyOf完成复制数组
int[] src={1,2,3};
int[] dest = new int[3];// dest 当前是 {0,0,0}
//这五个参数的含义
//源数组,源数组开始复制的位置,目标数组,目标数组开始复制的位置,从源数组拷贝多少个数据
System.arraycopy(src, 0, dest, 0, src.length);
System.out.println("dest=" + Arrays.toString(dest));//[1, 2, 3]
6.BigInteger类和BigDecimal类
应用场景
1.BigInteger适合保存比较大的整型
2.BigDecimal适合保存精度更高的浮点型
BigInteger和BigDecimal常用的方法
1.add 加
2.subtract 减
3.multiply 乘
4. divide 除
代码:
//BigInteger
BigInteger bigInteger = new BigInteger("23788888899999999999999999999");
BigInteger bigInteger2 = new BigInteger("1009999999999999999999999999999999999999999999999999999999999999999999999");
System.out.println(bigInteger);
//1. 在对 BigInteger 进行加减乘除的时候,需要使用对应的方法,不能直接进行 + - * /
//2. 可以创建一个 要操作的 BigInteger 然后进行相应操作
BigInteger add = bigInteger.add(bigInteger2);
System.out.println(add);//
BigInteger subtract = bigInteger.subtract(bigInteger2);
System.out.println(subtract);//减
BigInteger multiply = bigInteger.multiply(bigInteger2);
System.out.println(multiply);//乘
BigInteger divide = bigInteger.divide(bigInteger2);
System.out.println(divide);//除
//BigDecimal
BigDecimal bigDecimal = new BigDecimal("1999.11");
BigDecimal bigDecimal2 = new BigDecimal("3");
System.out.println(bigDecimal);
//1. 如果对 BigDecimal进行运算,比如加减乘除,需要使用对应的方法
//2. 创建一个需要操作的 BigDecimal 然后调用相应的方法即可
System.out.println(bigDecimal.add(bigDecimal2));
System.out.println(bigDecimal.subtract(bigDecimal2));
System.out.println(bigDecimal.multiply(bigDecimal2));
//System.out.println(bigDecimal.divide(bigDecimal2));//可能抛出异常ArithmeticException
//在调用divide (除法)方法时,指定精度即可. BigDecimal.ROUND_CEILING
//如果有无限循环小数,就会保留 分子 的精度
System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));
2.集合
1.集合的概述和框架体系
数组的缺点
1.长度开始时必须指定,不能更改
2.保存的数据必须为同一类型的数据
3.使用数组进行增删元素比较麻烦
引出集合
1.可以动态保存任意多个对象,使用比较方便
2.提供了一些类操作对象的方法:add、remove、set、get等
集合的框架体系
2.Collecton接口和常用方法
package com.base.collection_;
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);
// containsAll:查找多个元素是否都存在
System.out.println(list.containsAll(list2));//T
// removeAll:删除多个元素
list.add("聊斋");
list.removeAll(list2);
System.out.println("list=" + list);//[聊斋]
}
}
iterator = collection.iterator()
3.List接口和常用方法
基本介绍
List集合类中元素是有序,且可重复的
每个元素都有对应的顺序索引,即支持索引
List容器的元素都对应一个整数型的序号记载在其容器的位置,即可以根据序号存取容器中的元素
常用的List接口实现类有:ArrayList/LinkedList/Vector
常用方法
public class ListMethod {
@SuppressWarnings({"all"})
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三丰");
list.add("贾宝玉");
//在index = 1的位置插入一个对象
list.add(1, "小明");
System.out.println("list=" + list);
List list2 = new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(1, list2);
System.out.println("list=" + list);
// Object get(int index):获取指定index位置的元素
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位置的子集合
List returnlist = list.subList(0, 2);
System.out.println("returnlist=" + returnlist);
}
}
4.ArrayList底层结构和源码分析
基本介绍
ArrayList可以加入多个null
ArrayList是由数组【Object类型的数组 elementDara】来实现数据存储的
ArrayList基本等同于Vector,除了ArrayList线程不安全。但执行效率高
底层原理
(1)源码中有一个
private transient Object[] elementData;
属性,transient 表示瞬间,短暂的,表示该属性不会被序列化
(2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementDara容量为0,第一次添加时扩容elementDara为10,如需再次扩容(elementDara长度小于需要扩容后的长度时),则扩容elementDara为1.5倍
(3)如果使用的是指定大小的构造器,则初始值elementDara为指定大小,如需扩容,则扩容elementDara为1.5倍
5.Vector底层结构和源码分析
基本介绍
Vector底层也是由数组【Object类型的数组 elementDara】来实现数据存储的
Vector是线程同步的,Vector类的操作方法带有 synchronized
底层原理
(1)同样有一个数组 private Object[] elementData;
(2)当调用Vector无参构造器时,默认是10长度,因为源码中它直接调用有参构造器传了个10过去,如需扩容,则扩容elementDara为2倍
public Vector() {
this(10);
}
(3)当调用Vector有参构造器时,则初始值elementDara为指定大小,如需扩容,则扩容elementDara为2倍
Vector和String的比较
底层结构 | 版本 | 线程安全(同步)效率 | 扩容倍数 | |
ArrayList | 可变数组 | jdk 1.2 | 不安全,效率高 | (1)有参构造 1.5倍 (2)无参构造 默认10,第二次开始按1.5倍如需扩容,则扩容elementDara为2倍 |
Vector | 可变数组 | jdk 1.0 | 安全,效率不高 | (1)有参构造 2倍 (2)无参构造 默认10,第二次开始按2倍扩容 |
6.LinkedList底层结构
基本介绍
LinkedList底层实现了双向链表和双端队列特点
可以添加任意元素(元素可重复),包括null
线程不安全,没有实现同步
底层原理
LinkedList底层维护了一个双向链表
LinkedList中维护了两个属性 first和 last 分别指向 首节点和尾节点
每个节点(Node对象),里面有维护了 prev(上一个),next(下一个),item三个属性
所以LInkedList元素的添加和删除,是通过链子完成的,不是通过数组,相对来说效率高
模拟一个简单的双向链表
public class LinkedList01 {
public static void main(String[] args) {
//模拟一个简单的双向链表
Node jack = new Node("jack");
Node tom = new Node("tom");
Node hsp = new Node("老师");
//连接三个结点,形成双向链表
//jack -> tom -> hsp
jack.next = tom;
tom.next = hsp;
//hsp -> tom -> jack
hsp.pre = tom;
tom.pre = jack;
Node first = jack;//让first引用指向jack,就是双向链表的头结点
Node last = hsp; //让last引用指向hsp,就是双向链表的尾结点
//演示,从头到尾进行遍历
System.out.println("===从头到尾进行遍历===");
while (true) {
if(first == null) {
break;
}
//输出first 信息
System.out.println(first);
first = first.next;
}
//演示,从尾到头的遍历
System.out.println("====从尾到头的遍历====");
while (true) {
if(last == null) {
break;
}
//输出last 信息
System.out.println(last);
last = last.pre;
}
//演示链表的添加对象/数据,是多么的方便
//要求,是在 tom --------- 老师之间,插入一个对象 smith
//1. 先创建一个 Node 结点,name 就是 smith
Node smith = new Node("smith");
//下面就把 smith 加入到双向链表了
smith.next = hsp;
smith.pre = tom;
hsp.pre = smith;
tom.next = smith;
//让first 再次指向jack
first = jack;//让first引用指向jack,就是双向链表的头结点
System.out.println("===从头到尾进行遍历===");
while (true) {
if(first == null) {
break;
}
//输出first 信息
System.out.println(first);
first = first.next;
}
last = hsp; //让last 重新指向最后一个结点
//演示,从尾到头的遍历
System.out.println("====从尾到头的遍历====");
while (true) {
if(last == null) {
break;
}
//输出last 信息
System.out.println(last);
last = last.pre;
}
}
}
//定义一个Node 类,Node 对象 表示双向链表的一个结点
class Node {
public Object item; //真正存放数据
public Node next; //指向后一个结点
public Node pre; //指向前一个结点
public Node(Object name) {
this.item = name;
}
public String toString() {
return "Node name=" + item;
}
}
LinkedList增删改查
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();
System.out.println("linkedList=" + linkedList);
//修改某个结点对象
linkedList.set(1, 999);
System.out.println("linkedList=" + linkedList);
//得到某个结点对象
Object o = linkedList.get(1);
System.out.println(o);//999
//因为LinkedList 是 实现了List接口, 遍历方式
System.out.println("===LinkeList遍历迭代器====");
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println("next=" + next);
}
System.out.println("===LinkeList遍历增强for====");
for (Object o1 : linkedList) {
System.out.println("o1=" + o1);
}
System.out.println("===LinkeList遍历普通for====");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
7.ArrayList和LinkedList的比较
底层结构 | 增删的效率 | 改查的效率 | |
ArrayList | 可变数组 | 较低(数组扩容) | 较高 |
LinkedList | 双向链表 | 较高(链表追加) | 较低 |
8.Set接口和常用方法
基本介绍
1.无序(添加和取出顺序不一致),没有索引
2.不允许重复元素,所以最多包含一个null
3. 常用的Set接口实现类:HashSet、TreeSet
Set接口的遍历方式
1.迭代器
2.增强for
3.不能使用索引方式来for循环获取了
常用方法:set.add("tom"); set.remove("tom");
9.HashSet
基本介绍
HashSet的底层是HashMap,HashMap的底层是(数组+链表+红黑树)
底层原理
1.添加一个元素时,先得到hash值,然后转成 索引值(索引值是根据当前table长度按位与该元素的hash值得到的)
2.找到存储数据表table,看这个索引位置是否已经存放了元素
3.如果没有,直接加入
4.如果有,调用equals比较(所以判断一个元素是否相同是根据不同的类是否重写了equals决定的),如果相同,就放弃添加,如果不相同(需要比较该行所有的链表元素),则添加到最后
5.在jdk8中,如果一条链表的元素个数到达8时,并且table的大小将要到达64时,就会树化(红黑树),否则仍采用扩容机制
扩容和转成红黑树机制:
1.第一次添加时,table数组扩容到16,临界值(threshold(16))*加载因子(loadFactor(0.75))=12
2.当长度(size)达到12时就会扩容到12*2=32,新的临界值就是32*0.75=24,以此类推
3.这个长度(size)是 所有元素的和,每加一个元素size++