常用类
包装类Wrapper
- 针对八种基本数据类型相应的引用类型——包装类
- 有了类的特点,可以调用类的方法
基本数据类型 | 包装类 |
boolean | Booblean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
注:Object是所有类的父类,关系图中隐藏该父类
基本数据类型boolean对于的包装类关系图
基本数据类型char对应的包装类关系图
各数值类型对应包装类关系图
包装类和基本数据类型的转换
- 装箱:基本类型转包装类型;反之为拆箱。
- 自jdk5以后的自定装箱和拆箱方式
- 自动装箱底层调用valueOf方法,如:Integer.valueOf()
public class Integer01 {
public static void main(String[] args) {
// jdk5以前
// 手动装箱示范:int->Integer
int num=10;
Integer integer=new Integer(num);
Integer integer1=Integer.valueOf(num);
//手动拆箱
int i=integer.intValue();
// 自动装箱
int num2=20;
Integer integer2=num2; // 底层用的是Integer.valueOf(num2)
// 自动拆箱
int num3=integer2; // 底层任然使用intValue()方法
}
}
其他包装类的用法同理
包装类和String类型的相互转换
Integer和String
public class Wrapper {
public static void main(String[] args) {
// 方法一、包装类Integer转为String
Integer i=10; // 自动装箱
// 以i为基本数值转成str1,对i的原数值没有影响
String str1=i+"";
// 方法二
String str2 = i.toString();
// 方法三
String str3 = String.valueOf(i);
String str4="123456";
// String->包装类(Integer)
Integer.parseInt(str4);
Integer i2=Integer.parseInt(str4);// 自动装箱
Integer i3=new Integer(str4); // 构造器
}
}
包装类方法
Integer类和Character类的常用方法。其他方法需要使用时自行查找。
public class Wrapper {
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'));//转成小写
}
}
String
- String对象用于保存字符串,也就是一组字符序列
- 字符串常量对象是用双引号括起的字符序列。例如:"hello"。
- 字符串的字符使用Unicode字符编码,一个字符占两个字节(不区分字母还是汉字)。
- String类常用的构造方法
String s1=new String();
String s2=new String(String original);
String s3=new String(char[] a);
String s1=new String(char a,int starIndex,int count);
String类图结构
- String实现了Serializable接口,说明String可以串行化;可以在网络上传输。
- Sting实现了Comparable接口,说明String可以比较。
- String是final类;不能被继承。
- String有属性 private final char value[];用于存放字符串内容,value是一个final类型,地址不可修改(value不能指向新地址,但是单个字符内容可修改)。
public class Str {
public static void main(String[] args) {
String s = "rick";
final char[] value = {'a', 'b', 'c'};
char[] value2 = {'d', 'e', 'f'};
// value=value2; final约束不可以修改value地址
value[0] = 'B';
for (int i = 0; i < value.length; i++)
System.out.println(value[i]);
}
}
创建String对象的两种方式
- 方式一,直接赋值:
String s="hello";
- 方式二,调用构造器:
String s2=new String("hello");
- 方式一:先从常量池查看是否有"hello"数据空间,如果有,直接指向;没有则重新创建然后指向。s最终指向常量池的空间地址。
- 方式二:先在堆中创建空间,里面维护value属性,指向常量池的hello空间。如果常量池没有"hello",重新创建,有则直接通过value指向。最终指向的是堆中的空间地址。
创建String对象两种方式的内存布局图
调用intern方法时如果池中已经包含一个等于此String对象的字符串(用equals(Object)方法确定)。则返回池中字符串,否则,把String对象的字符串添加到池中,并返回对象的引用。
public class _Str {
public static void main(String[] args) {
String s1 = "hello";
String s2 = new String("hello");
System.out.println(s1.equals(s2));
System.out.println(s1 == s2.intern()); // s2.intern最终返回的是常量池中的常量池地址
System.out.println(s1 == s2);
}
}
String内存布局示范代码(根据代码画出内存布局图掌握内存布局)
public class _Str {
public static void main(String[] args) {
Person person = new Person();
person.name="rick";
Person person1 = new Person();
person1.name="rick";
System.out.println(person.name.equals(person1.name));
System.out.println(person==person1);
System.out.println(person.name=="rick");
String s1=new String("hi");
String s2=new String("hi");
System.out.println(s1==s2);
}
}
class Person{
public String name;
}
字符串的特性
public class _Str {
public static void main(String[] args) {
String s1="hi"+"rick"; // 编译器会优化为[String s1="hirick";]所以会创建一个对象
String s2="ab";
String s3="cd";
String s4=s2+s3; //执行步骤:
// 1.创建一个StingBuilder s=new StringBuilder()
// 2.执行s.append("ab");
// 3.执行s.append("cd");
// 4.执行String s4 = s.toString();
// 最终s4指向堆中的对象(String)value[]->常量池中的"abcd"
String s5="abcd";
System.out.println(s4==s5);
System.out.println(s4.equals(s5));
T t = new T();
t.chage(t.str0, t.ch);
System.out.println(t.str0);
System.out.println(t.ch);
}
}
class T {
String str0 = new String("hello");
final char[] ch = {'j', 'a', 'v', 'a'};
public void chage(String str,char ch[]) {
str0 = "java";
ch[0] = 'N';
}
}
String的常用方法
String类是保存字符串常量的。每次更新都需要重新开辟空间,效率低,所以java设计者提供了StringBuffter和StringBuild增强String的功能,并提高效率。
String常用方法
public class _StrMethod {
public static void main(String[] args) {
String str1 = "hello";
String str2 = "Hello";
System.out.println(str1.equals(str2));//比较两个字符串内容
// 2.equalsIgnoreCase 忽略大小写的判断内容是否相等
String username = "johN";
if ("john".equalsIgnoreCase(username)) {
System.out.println("Success!");
} else {
System.out.println("Failure!");
}
// 3.length 获取字符的个数,字符串的长度
System.out.println("Jack三".length());
// 4.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
// 5.lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从 0 开始,如果找不到,返回-1
s1 = "wer@terwe@g@";
index = s1.lastIndexOf('@');
System.out.println(index);//11
System.out.println("ter 的位置=" + s1.lastIndexOf("ter"));//4
// 6.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(0, 5));//hllo
// 1.toUpperCase 把字符串内字母全部转换成大写
String s2 = "HEllo";
System.out.println(s2.toUpperCase());
// 2.toLowerCase 把字符串内所有字符转为小写
System.out.println(s2.toLowerCase());
String s3 = "jack";
//
s3 = s3.concat("hello").concat("every").concat("day");
System.out.println(s3);
s3 = "jackhelloeveryday";
// replace 把s3中所有hello 换成Hi,注意方法只对返回的结果处理,对原数据没有影响
s3 = s3.replace("hello", "Hi");
System.out.println(s3);
String s4 = "Aa,Bb,Cc,Dd,Ee";
// 以 , 为标准进行分割返回一个数组
String[] split = s4.split(",");
System.out.println("逗号分隔开的单个数据分别是:");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
String s5 = "hello";
// toCharArray 把字符串转为字符数组
char[] chars0 = s5.toCharArray();
for (int i = 0; i < chars0.length; i++) {
System.out.println(chars0[i]);
}
// compareTo 比较两个字符串大小前者大返回正数否则为负相等为0
// 1.长度相同,每个字符相同返回0 2.长度相同或不同,比较时可以区分大小写就返回s6-s7(具体查看源码)3.前面部分相同就s6.length-s7.length
String s6 = "rick";
String s7 = "jack";
System.out.println(s6.compareTo(s7));// 返回 s7-s6的值
String name1="tom";
int age=18;
double score=97.5/3;
char gender='男';
String show="姓名"+name1+"年龄"+age+"平均成绩"+score+"性别"+gender;
System.out.println(show);
// %s,%d 等这些叫做占位符,由后面的变量来替换,占位符具体用法查看C语言
String info=String.format("年龄%s年龄%d平均成绩%.2f性别:%c",name1,age,score,gender);
System.out.println(info);
}
}
其他方法通过jdk api 1.8_google文档查看
StringBuffer类
java.lang.StrinngBuffer代表可变的字符序列,可以对字符串内容进行增删。很多方法与String相同,但StringBuffer是可变长度的。
- StrinngBuffer直接父类是AbstractStringBuilder
- StringBuffer实现了Serializable,即StringBuffer的对象可以串行
- 在父类AbstractStringBuilder中有属性char[] value,不是final。
- 该value数组存放字符串内容,所以存放在堆中(不是常量池)。
- StringBuffer是一个final类。
String对比StringBuffer
- String保存的是字符串常量,里面的值不能修改,String每次更新实际上是更新地址效率低(本质原因是
private final char value[];
) - StringBuffer保存的是字符串变量,里面的值可以修改,且修改内容不用每次更新地址效率高(
char value[];
存放在堆中)
StringBuffer构造器
StringBuffer构造器
public class Buffer {
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer(); // 创建一个大小为16的char[],用于存放字符内容
StringBuffer stringBuffer2 = new StringBuffer(100); // 指定创建一个大小为100的char[]。
StringBuffer hello = new StringBuffer("hello"); // 通过给String创建一个StringBuffer,char[]大小就是一个str.length+16
}
}
String和StringBuffer的相互转换
查看代码
public class StringAndBuffer {
public static void main(String[] args) {
// String转为StringBuffer
String str="hi rick";
// 使用构造器转换
StringBuffer stringBuffer = new StringBuffer(str); //返回的才是StringBuffer对象对String本身没有影响
// 使用append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1= stringBuffer1.append(str);
// StringBuffer转String
StringBuffer stringBuffer2 = new StringBuffer("hello,jack");
// 使用StringBuffer提供的toString方法直接转换
String s = stringBuffer2.toString();
// 使用构造器
String s1 = new String(stringBuffer2);
}
}
StringBuilder类
是一个可变的字符序列,此类提供一个与StringBuffer兼容的API,但是不保证同步(StringBuilder存在多线程问题)。该类被设计用于StringBuffer的简易替换,用在字符串缓冲区被单个线程使用时。如果可能,建议优先采用该类,因为多数情况下,他比StringBuffer更快。
- 通过继承关系图得知StringBuilder继承了AbstractStringBuilder类
- 实现了Serializable,说明StringBuilder对象是可以串行化(该对象可以网络传输,也可以保存到文件)同时还是final类
- StringBuilder对象字符依旧存放在其父类AbstractStringBuilder类,所以字符序列存放在堆中
- StringBuild的方法,没有做互斥处理(没有synchronized关键字,因此推荐在多线程的情况下使用)
在StringBuilder上的主要操作是append和insert方法,可重载这些方法,以接受任意类型。
String、StringBuilder、StringBuffer的比较
- StringBuilder和StringBuffer非常类似均代表可变的字符序列,且方法一样。
- String:不可变字符序列,效率低、但是代码复用率高
- StringBuffer:可变字符序列,增删效率较高、线程安全(源码可以看到方法被
synchronized
修饰)。 - StringBuffer:可变字符序列,效率最高、线程不安全。
String s="a"; // 创建了一个字符串
s+="b"; // 实际上原来的“a”对象已经丢弃,现在产生新字符串s+"b"("ab")
//如果多次执行(循环)这些改变字符串操作会导致大量字符串对象存留在内存中,降低效率
System.out.println("结论:如果这样的操作放在循环中会极大地影响性能,所以对String做大量修改时,不要用String而是StringBuffer。");
使用总结:
- 如果字符串存在大量修改操作,通常使用StringBuffer(多线程)或StringBuilder(单线程)
- 如果修改字符串操作较少,被多个对象引用,使用String,如配置信息等
Math类
基本介绍:包含用于基本数学运算的方法(均为静态方法),例如初等指数,对数、平方根、三角函数。
Math常用方法
public class MathMethod {
public static void main(String[] args) {
System.out.println("Math常用的方法");
//看看 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.0
//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=2,b=7,=> (int)(a+Math.random()*(b-a+1))=(int)(2+Math.random()*6)
for (int i = 0; i < 100; i++) {
System.out.print((int) (2 + Math.random() * (7 - 2 + 1))+" ");
}
System.out.println("\n获取a-b之间的随机整数公式:int number=(int)(Math.random()*(b-a+1)+a)");
//max , min 返回最大值和最小值
int min = Math.min(1, 9);
int max = Math.max(45, 90);
System.out.println("\nmin=" + min);
System.out.println("max=" + max);
}
}
Array类
public class ArrayMethod {
public static void main(String[] args) {
Integer[] integers = {1, 2, 3};
// 遍历数组
/*for (int i = 0; i < integers.length; i++) {
System.out.println(integers[i]);
}*/
// 直接使用Array.toString方法,显示数组
System.out.println(Arrays.toString(integers)); // 查看toString(选中【Ctrl】+【b】)方法可以知道返回的内容
Integer arr[] = {-1, 2, -3, 4, 5, -6, 7, 0};
// 进行排序 1、可以使用冒泡排序,也可以直接使用Array.sort方法直接排序
Arrays.sort(arr); // 默认排序;因为数组是引用类型传入的是地址排序后会修改实参arr
Arrays.sort(arr, new Comparator() { // 调用定制排序时,传入两个参数1.排序数组arr,2.实现Comparator()接口的匿名内部类
// 源码分析1、Array.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、执行传入的匿名内部类
// 5、 public int compare(Object o1, Object o2) 返回的值>0还是<0 会影响整个排序的结果
@Override
public int compare(Object o1, Object o2) { // 要求实现compare方法
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i1-i2; // 从小到大;体现接口编程的方式(对匿名内部类下断点调试)
// return i2-i1;
}
});
// sort是重载的也可以通过传入一个Comparator实现定制排序
System.out.println(Arrays.toString(arr));
}
}
查看代码
public class ArrayCustomSort {
public static void main(String[] args) {
int arr[] = {0, -1, 2, 3, -5, -10};
bubble1(arr);
System.out.println("冒泡排序后");
System.out.println(Arrays.toString(arr));
bubble2(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
int i1 = (Integer) o1; //拆箱
int i2 = (Integer) o2;
// return i1 - i2; // 小到大
return i2-i1; //大到小
}
});
System.out.println("自定义排序后:"+Arrays.toString(arr));
}
// 冒泡排序
public static void bubble1(int arr[]) {
int temp = 0;
for (int i = 0; i < arr.length; 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 bubble2(int[] arr, Comparator comparator) {
int temp = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
// 数组的排序由comparator.compare(arr[j], arr[j + 1])返回的值决定
if (comparator.compare(arr[j], arr[j + 1]) > 0) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
二分查找
public class ArrayMethod {
public static void main(String[] args) {
// binarySearch通过二分查找,要求必须是排序好(有序的)的数组
Integer[] arr = {-1,0,1,2,3,4,6,8,10};
int index=Arrays.binarySearch(arr,10);
System.out.println(index); // 数组不存在查找的元素则返回return -(low + 1); low指查找元素应该存在的位置
}
}
Array常用类
public class ArrayMethod {
public static void main(String[] args) {
// binarySearch通过二分查找,要求必须是排序好(有序的)的数组
Integer[] arr = {-1,0,1,2,3,4,6,8,10};
int index=Arrays.binarySearch(arr,10);
System.out.println(index); // 数组不存在查找的元素则返回return -(low + 1); low指查找元素应该存在的位置
// copyOf 数组元素复制:从arr数组中拷贝arr.length个元素到newArr数组中。
// 拷贝的长度大于arr.length,超出部分添加null,拷贝长度小于0抛出异常
// 底层使用System.arraycopy()
Integer[] newArr=Arrays.copyOf(arr,arr.length);
System.out.println("复制的数组:"+Arrays.toString(newArr));
// ill数组元素填充
Integer num[]=new Integer[]{77,177,777};
// 用99填充num数组换言之用99替换所有原来的元素
Arrays.fill(num,99);
System.out.println("数组填充后:"+Arrays.toString(num));
// equals 比较两个数组是否完全一致
Integer[] arr2 = {-1,0,1,2,3,4,6,8,10};
// 如果arr和arr2数组元素一样返回true
// 如果不完全一样返回false
boolean equals=Arrays.equals(arr,arr2);
System.out.println(equals);
// asList把一组值转为list
// asList方法,会把(2,3,4,5,8,-1,0)数据转为一个集合
// 返回的asList变异类型List接口
// asList运行类型是Array类的静态内部类:private static class ArrayList<E> extends AbstractList<E>
// implements RandomAccess, java.io.Serializable
List<Integer>asList=Arrays.asList(2,3,4,5,8,-1,0);
System.out.println("aslist="+asList);
System.out.println("asList的运行类型是"+asList.getClass());
}
}
Array应用练习
public class ArrayMethod {
public static void main(String[] args) {
Book[] books = new Book[4];
books[0] = new Book("01", 100);
books[1] = new Book("002", 200);
books[2] = new Book("0003", 300);
books[3] = new Book("00004", 400);
//price从小到大
Arrays.sort(books, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
Book book1 = (Book) o1;
Book book2 = (Book) o2;
double val = book2.getPrice() - book1.getPrice();
if (val > 0) {
return -1;
} else if (val < 0) {
return 1;
} else {
return 0;
}
}
});
System.out.println(Arrays.toString(books));
//price从大到小
Arrays.sort(books, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
Book book1 = (Book) o1;
Book book2 = (Book) o2;
double val = book2.getPrice() - book1.getPrice();
if (val > 0) {
return 1;
} else if (val < 0) {
return -1;
} else {
return 0;
}
}
});
System.out.println("\n" + Arrays.toString(books));
// 按书名长度排序,长到短
Arrays.sort(books, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Book book1 = (Book) o1;
Book book2 = (Book) o2;
return book2.getName().length() - book1.getName().length();
}
});
System.out.println("\n" + Arrays.toString(books));
}
}
class Book {
private String name;
private double price;
public Book(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;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
"price=" + price +
'}' + "\n";
}
}