1.什么是内部类,分为哪些?
内部类:
在Java中,一个类A中定义类B,将类B称为类A的内部类;
分类:
成员内部类/局部内部类
2.直接访问非静态的成员内部类的成员方法的格式?(重点)
class Outer{
class Inner{
public void show(){
//...
}
}
}
//外部类名.内部类名 对象名 = new 外部类名().new 内部类名() ;
Outer.Inner oi = new Outer().new Inner() ;
3.静态的成员内部类的特点以及直接访问静态成员内部类的成员方法的格式?
静态的成员内部类的特点:
静态的成员内部类的成员方法里面:访问外部类的成员必须为静态
class Outer{
private static int num = 20 ;
static class Inner{
public void show(){
System.out.println(num) ;
System.out.println("show Inner") ;
}
public static void show2(){
System.out.println("show2 Inner") ;
}
}
}
//show2()方法静态的
Outer.Inner.show2() ;
//show()方法--创建内部类对象访问
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
4.接口和抽象类的区别?
1)成员区别
接口:
成员变量:只能是常量
成员方法:只能是抽象方法
构造方法:没有
抽象类:
成员变量:既可以是常量,也可以是变量
成员方法:既可以抽象方法,也可以非抽象方法
构造方法:存在 有参构造/无参构造方法,目的为了类的数据进行构造初始化!----分层初始化
2)关系区别
类与类:继承关系,单继承,可以多层继承,不支持多继承
类接口:实现关系,一个类继承另一个类的同时,可以实现多个接口
接口与接口:继承关系,支持单继承,多继承,多层继承!
3)设计理念
抽象类:存在继承关系,体现的是一种"is a"的关系:当一个类A是类B的一种,使用继承!
接口: 与子实现类实现关系,事物本身不具备的功能,体现的一种"like a"的关系(额外扩展功能)
5.jdk8以前局部内部类访问局部变量为什么加入final修饰?
局部变量的生命周期,随着方法调用而存在,随着方法调用结束而消失;当
方法结束了,但是局部内部类正在被创建对象,通过成员方法访问里面的局部变量,就会导致访问不到,此时这个变量
必须加入final修饰,为自定义常量
6.匿名内类的格式以及本质 (重点)
格式:
new 类名或者接口名(){
重写方法(){
...
}
} ;
本质:
继承了该类或者是实现了该接口的子类对象!
02_方法的返回值是一个接口_可以使用接口匿名内部类
package ReturnNiMingJieKou;
interface Nb{
void nb();
}
class NbDemo {
public Nb NbMethod(){
return new Nb(){
@Override
public void nb() {
System.out.println("返回值是接口的匿名对象");
}
};
}
}
public class Demo5 {
public static void main(String[] args) {
NbDemo nb=new NbDemo();
Nb nb1 = nb.NbMethod();
nb1.nb();
}
}
补充:
内部类的方法可以访问外部类的所有方法 包括私有
选择排序
使用角标0的元素依次和后面的元素作比较
比较的次数是数组长度-1;
to String
jvm提供的工具,将任何数组自动转换为string数组
package XuanZePaiXu;
import java.util.Arrays;
//需要返回的
public class Demo1 {
public static void main(String[] args) {
int arr[] = {24, 42, 12, 6, 89};
printArray(arr);
int Myarr[]=Demo(arr);
String str = Arrays.toString(Myarr);//第三方提供jdk提供的Arrays工具类:将任何的数组转换成String ["元素1", "元素2", ]---toString()
System.out.println("-----------------");
System.out.println(str);
}
public static int[] Demo(int[] arry){
for(int x=0;x<arry.length-1;x++){
for(int y=x+1;y<arry.length;y++){
if (arry[x]>arry[y]){
int temp=arry[y];
arry[y]=arry[x];
arry[x]=temp;
}
}
}
return arry;
}
//遍历
public static void printArray(int[] array){
System.out.print("[") ;
for(int x = 0 ;x < array.length ; x++){
if(x ==array.length-1){
System.out.println(array[x]+"]");
}else{
System.out.print(array[x]+", ");
}
}
}
}
package XuanZePaiXu2;
public class Demo2 {
public static void main(String[] args) {
int arr2[]={89,32,4,12,76};
System.out.println("排序前");
ArrayPrint(arr2);
System.out.println("排序后");
for(int x=0;x<arr2.length-1;x++){//x是循环次数
for(int y=x+1;y<arr2.length;y++){//y是角标
if(arr2[x]>arr2[y]){
int temp = arr2[y] ;
arr2[y] = arr2[x] ;
arr2[x] = temp ;
}
}
}
ArrayPrint(arr2);
}
public static void ArrayPrint(int arr[]){
System.out.print("[");
for(int a=0;a<arr.length;a++){
if(a== arr.length-1){
System.out.println(arr[a]+" ]");
}else {
System.out.print(arr[a]+", ");
}
}
}
}
常用类重点:Object/String/StringBuffer/…
Object类是所有类的根类,所有类的超类也就是父类
getClass
-
- 常用类以及后面高级特性:集合框架,多线程,io流,网络编程,反射等等都是使用jdk提供API - API:Application Programming Interface:应用程序接口文档 - 需要将重点的类的重点功能--记住 - 举例:String类的拆分/将字符串转换成字符数组等等 - java.lang.Object类:所有的类父类(包括自定义的类) - 重点功能: - public final Class getClass():获取正在运行的类; (返回字节码文件对象) (跟后面反射有关系) - 面试题: - 在Java中获取一个类的字节码文件对象的方式有几种? - 有三种: - 1)public final Class getClass():获取正在运行的类; (返回字节码文件对象) - 2)在Java中任意类型的class属性 举例: Class c = 类名.class - 3)Class类提供的一个静态方法 - public static Class forName(String classPathName) :参数为当前类的全限定名称
public class ObjectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//创建两个学生对象
Student s1 = new Student() ;
Student s2 = new Student() ;
//public final Class getClass():获取正在运行的类; (返回字节码文件对象)
Class c1 = s1.getClass() ;
System.out.println(c1) ;//class com.qf.object_01.Student (class标记类 包名.类名-->类的全限定名称)
Class c2 = s2.getClass() ;
System.out.println(c2) ;
System.out.println(c1==c2) ;//true:s1和s2都是 com.qf.object_01.Student:类就加载一次,对象可以不断new!
System.out.println("------------------------------------------") ;
//在Java中任意类型的class属性:也可以获取到一个类的字节码文件!
Class c3= Student.class ;
System.out.println(c3) ;
System.out.println(c3==c2);
System.out.println("-----------------------------------------") ;
//第三种获取字节码文件方式:Java提供Class类---跟反射相关的-提供静态功能-->返回值是它自己本身
//public static Class forName(String className) throws ClassNotFoundException
//这个方法在使用过程中,可能出现类找不到异常,谁调用这个方法,必须对这个异常处理---给上面抛出
//这个方法的参数需要传递的是当前类的"全限定名称"
// Class c4 = Class.forName("Student") ;//这里必须是全限定名称
Class c4 = Class.forName("com.qf.object_01.Student") ;
System.out.println(c4) ;
System.out.println(c4==c3);//true
}
}
toString
Object类的toString()
public String toString():返回对象的字符串表示形式。
结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法(否则,打印出来的是地址值!)
public int hashCode():返回对象的哈希码值,不同的对象,它的哈希码值不同
(理解为 "地址值",它不是实际意义的地址值----通过哈希算法算出来的)
/**
* 定义一个Teacher类
*/
//public class Teacher extends Object {
public class Teacher {//默认继承Object类
private String name ; //姓名
private int age ; //年龄
public Teacher(){}
public Teacher(String name,int age){
this.name = name ;
this.age = age ;
}
/* public String toString(){
return "姓名是:"+name+",年龄是:"+age;
}*/
//idea生成(Alt+INSERT--to String)
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
equlas
==和equals的区别:
==:连接的是两个基本数据类型:比较的数据值是否相同
连接的是两个引用类型的数据,比较的是两个对象的地址值是否相同
Object的equals():默认比较的是两个对象的地址值是否相同,子类重写了equals(),就比较两个对象的内容是否相同
字符串常量相加:
先相加,然后看结果,是否在常量池中,如果有,直接返回值地址;否则开空间
字符变量相加:
先在常量池开辟空间,然后在操作;
equals:Object的equaels方法默认比较的是两个对象的地址值相同,
如果你要比较成员信息的内容是否相同,必须重写Object的equals方法以及 hashCode,重写之后比较的是内容是否相同(成员信息)
equals重写之后,是比较里面的每一个成员信息是否一样,如果都一样;
还有比较两个成员对应的hashCode是否一样,如果一样,是同一个人!
clone
Object的克隆方法:创建并返回此对象的"副本"----前提是自定义的类型必须实现Cloneable接口,否则无法克隆!
protected Object clone() throws CloneNotSupportedException
如果一个接口没有成员变量/成员方法,叫“标记接口”
package clone;
class Woff implements Cloneable{
String name3;
int age3;
public Woff(){}
@Override
public String toString() {
return "Woff{" +
"name3='" + name3 + '\'' +
", age3=" + age3 +
'}';
}
//重写克隆方法实现子实现类
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Woff(String name3, int age3) {
this.name3 = name3;
this.age3 = age3;
}
}
public class Test5 {
public static void main(String[] args) throws CloneNotSupportedException {
Woff W=new Woff();
W.age3=33;
W.name3="huitailang";
System.out.println(W);
Object clone = W.clone();
Woff W2= (Woff) clone;
System.out.println(W2);
}
}
Object类的clone方法里被native本地方法–非java语言实现
JNI:Java Native Interface:本地接口 通过java语言调用底层语言C
finalize方法和垃圾回收器
Object类的垃圾回收方法
protected void finalize()throws Throwable--跟gc垃圾回收器有关系
当jvm开启垃圾回收器的时候,就会回收堆内存中没有更多引用的对象(new 出来的东西)
当前垃圾回收器开始运行,会调用Object类的finalize()方法,来回收对象,子类重写了,会调用子类的finalize方法
Scanner类
java.util.Scanner:文本扫描器(键盘录入数据的)
构造方法:
public Scanner(InputStream source):
创建一个文本扫描器对象,里面参数是字节输入流,读取键盘录入的一些数据
成员方法:
获取功能:除过不能录入char类型之外.都可以录入!
int nextInt():录入int类型
String next():录入字符串
String nextLine():录入一行字符串
....
判断功能
boolean hasNextXXX()方法:判断下一个录入的是为XXX类型
细节:
如果先录入int,在录入String,在录入String(使用String nextLine())---String的值会被漏掉;
解决方案:
1)使用String next():录入单个字符串(推荐)
2)在使用nextLine()之前,重新创建一个新的Scanner对象;
需求:
键盘录入5个学生的语文成绩,数学成绩,英语成绩,姓名---对学生成绩排序
int chinses;
int math;
int english;
String name ;
//全部录入的时候---全部都使用String录入的 --->将 语文成绩,学生成绩/英语成绩---数字字符串--->转换int
"98" 数字字符串---->98 int
开发中:类型转换
需求的结果可能是A类型,但是中间的业务过程,可能需要B类类型的功能,将A类型---B类型;
使用完功能之后,再B类型---转换A类型!
String
String类:
代表字符串,是一个常量,创建之后,其值不能更改!
举例:
String s = "abc" ; 格式 开发中定义字符串就这个格式!
字符串的底层就是一个字符数组组成!char[]--->String
构造方法
public String():创建字符串对象
public String(String original):将指定的字符串传进去,构造一个字符串对象
public String(char[] value):将字符串数组---构造成String
public String(char[] value,int offset,int count):将一部分字符数组转换成String
public String(byte[] bytes)将字节数组---构造成String
public String(byte[] bytes, int offset,int length):将一部分字节数组---构造成String
转换问题
如果存在类型转换问题:
已知char[]--->String public String(char[] value)
已知byte[]--->String public String(byte[] bytes)
如果仅仅表示定义一个String对象---推荐的格式
String 变量名 = "字符串常量" ;
面试题
例子:
public class StringDemo {
public static void main(String[] args) {
// public String():创建字符串对象
String s = new String() ;
System.out.println("s:"+s) ;//打印不是地址,而空字符串,String类重写了Object类的toString()
System.out.println("----------------------------------------");
// public String(String original):将指定的字符串传进去,构造一个字符串对象
String s2 = new String("hello") ;
System.out.println("s2:"+s2) ;
System.out.println("---------------------------------------------") ;
//public String(char[] value):将字符串数组---构造成String
char[] chs = {'高','圆','圆'} ;
String s3 = new String(chs) ;
System.out.println("s3:"+s3) ;
System.out.println("----------------------------") ;
//public String(char[] value,int offset,int count):将一部分字符数组转换成String
String s4 = new String(chs,1,2) ;
System.out.println("s4:"+s4);
System.out.println("-------------------------------");
// public String(byte[] bytes)将字节数组---构造成String :
byte[] bytes = {97,98,99,100,101} ;
String s5 = new String(bytes) ;//转换过程,将每一个数据找ASII码表对应的字符值,构造成字符串
System.out.println("s5:"+s5) ;//abcde
System.out.println("--------------------------------") ;
// public String(byte[] bytes, int offset,int length)
String s6 = new String(bytes,2,3) ;
System.out.println("s6:"+s6) ;
}
}
面试题
s1和s2有什么区别?
String s1 = "hello" ;
String s2 = new String("hello") ;
第一个格式:
创建一个对象,直接在常量池中创建;
第二个格式:
需要在堆内存开辟空间,而且指向常量池地址:内存创建了两个对象!
两个都是创建字符串实例,但是推荐第一种,从内存角度考虑,消耗内存资源不严重!
String
特点:字符串不变:字符串的值在创建后不能被更改
因为String对象是不可变的,所以它们可以被共享。
String类获取功能
1)public char charAt(int index) 获取指定索引值对应的字符
2)public int length() :字符串特有功能:获取字符串长度
3)public String concat(String str):拼接功能 将指定的字符串拼接到该字符串末尾,获取新的字符串
4)public int indexOf(String str)返回指定字符串第一次出现索引值
public int lastIndexOf(String str):返回指定子字符串最后一次出现的索引值
5)public String[] forsplit(String regex):字符串拆分功能
6)截取功能
public String substring(int beginIndex,int endIndex)
从指定位置开始,截取到endIndex-1处结束,包前不包后
public String substring(int beginIndex)
从指定位置开始默认截取到末尾!
数组中length属性
String类中有length()数组方法
例子
public class StringDemo4 {
public static void main(String[] args) {
String s = "helloworld" ;
//public char charAt(int index) 获取指定索引值对应的字符
/*char ch = s.charAt(0) ;
System.out.println(ch);
System.out.println(s.charAt(1));
System.out.println(s.charAt(2));
System.out.println(s.charAt(3));
System.out.println(s.charAt(4));
System.out.println(s.charAt(5));
System.out.println(s.charAt(6));*/
//System.out.println(s.length());
//charAt(int index)+length()可以遍历字符串
for(int x = 0 ; x < s.length(); x++){
char ch = s.charAt(x) ;//获取指定索引值对应的字符
System.out.print(ch+"\t");
}
System.out.println();
System.out.println("---------------------------------------------");
//public String concat(String str):拼接功能 将指定的字符串拼接到该字符串末尾,获取新的字符串
//传统的字符串拼接+
System.out.println("hello"+10);
System.out.println(100+"name"+"is"+"hello");
String str = s.concat("高圆圆");
System.out.println(str);
System.out.println("---------------------------------------------");
//public int indexOf(String str)返回指定字符串第一次出现索引值
System.out.println(s.indexOf("o"));
System.out.println(s.lastIndexOf("o"));
System.out.println("---------------------------------------------------------") ;
//public String[] split(String regex) :拆分
String s2 = "Java-Python-C-Golang-R-Hadoop" ;
String[] strArray = s2.split("-"); //字符串数组
//遍历字符串数组
for(int x = 0 ; x < strArray.length ; x++){
System.out.print(strArray[x] +"\t");
}
System.out.println();
System.out.println("--------------------------------------------------------------");
/**
* public String substring(int beginIndex,int endIndex)
* 从指定位置开始,截取到endIndex-1处结束,包前不包后
* public String substring(int beginIndex)
* 从指定位置开始默认截取到末尾!
*/
String ss = s.substring(5, 8);
System.out.println(ss);
System.out.println(s.substring(5));
}
}
String类常用的转换功能
String类的常用的转换功能
public byte[] getBytes(): 将字符串转换成字节数组 (编码过程:将能看懂的东西--->变成看不懂的!)
(使用平台默认字符集)
public char[] toCharArray() :将字符串转换成字符数组 (使用居多)
public static String valueOf(常见的基本类型int/long/double/float/boolean/Object):
String的万能方法:将上面的常用类型--转换成String
public String toUpperCase():将指定字符串转换成大写
public String toLowerCase():将指定字符串转换成小写
public class Test4 {
public static void main(String[] args) {
int s=100;
String s2=String.valueOf(s);//String的万能方法:将上面的常用类型--转换成String
System.out.println(s2);
}
}
例子
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class StringDemo5 {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "中国" ;
//public byte[] getBytes(): 将字符串转换成字节数组 (编码过程:将能看懂的东西--->变成看不懂的!)
//idea设置的平台字符集:utf-8:一个中文三个字节
byte[] bytes = s.getBytes() ;
//System.out.println(bytes) ;
//将数组---转换成String--->Arrays数组工具类 toString(任意类型数组)
System.out.println(Arrays.toString(bytes));
System.out.println("---------------------------------") ;
//今天上午:String(byte[] byte) :解码--->将卡不懂的字节---变成看懂的字符串 (默认字符集utf-8)
String str = new String(bytes) ;//使用指定gbk格式进行解码 或者默认字符集进行解码
System.out.println(str) ;
System.out.println("------------------------------------------") ;
String ss = "helloJavaEE" ;
//public char[] toCharArray():将字符串转换成字符数组
char[] chs = ss.toCharArray();
//遍历字符数组
for(int x = 0 ; x < chs.length ; x++){
char ch = chs[x] ; //接收每一个字符
System.out.print(ch+"\t");
}
System.out.println();
System.out.println("---------------------------------------------------") ;
int i = 100 ;
System.out.println(i) ; //i是int类型
String result = String.valueOf(i);
System.out.println(result);//"100" 数字字符串
System.out.println("--------------------------------------------------") ;
System.out.println(ss.toLowerCase());
System.out.println(ss.toUpperCase());
}
}
String类常用的判断功能
String类判断功能以及其他功能:
public boolean constains(String str):判断大串中是否包指定的子字符串
public boolean equals(Object anObject)):比较两个字符串内容是否相同
public boolean equalsIgnoreCase(String anotherString)):忽略大小写比较
public boolean startsWith(String prefix):字符串是否以指定的前缀开头
public boolean endsWith(String str):字符串是否以指定的后缀结尾
例子
public class StringDemo {
public static void main(String[] args) {
String s = "helloworldJavaEE" ;
System.out.println(s.contains("owo"));
System.out.println(s.contains("ak47"));
System.out.println("-----------------------------");
System.out.println(s.equals("HelloworldJavaEE"));//区分大小写
System.out.println(s.equalsIgnoreCase("HelloworldJavaEE"));
System.out.println("--------------------------------") ;
System.out.println(s.startsWith("hel"));
System.out.println(s.endsWith("EE"));
System.out.println("---------------------------------") ;
//public String replace(char oldChar,char newChar)替换功能:使用指定的新的字符替换以前的字符
System.out.println(s.replace('l','*'));
System.out.println("------------------------------------") ;
String s1 = " hello ";
System.out.println("s1--->"+s1) ;
String s2 = s1.trim() ;
System.out.println("s2--->"+s2) ;
}
}
两个字符串按照字典顺序比较结果
两个字符串--->底层是以字符数组存储-获取字符数组长度,获取长度的最小值
使用最小值作为 while循环条件, 如果没有取到最小值,一直循环,
循环逻辑:
通过获取两个字符数组的每一个字符,如果都相同,最终临界条件达到 ,两个字符数组长度相减
如果获取到字符,如果两个字符不相等,直接是两个字符---对应的ASCII码表的值相减---直接得到字典顺序的值!
面试题:
* String s1 = "hello" ;
* String s2 = "hel" ;
* 这个两个字符串按照字典顺序比较结果是怎么计算的?
public class StringTest {
public static void main(String[] args) {
String s1 = "hello" ;
String s2 = "hel" ;
//public int compareTo(String another)
System.out.println(s1.compareTo(s2)) ;
System.out.println("-----------------------------") ;
String s3 = "abc" ;
int i = s1.compareTo(s3);
System.out.println(i);
}
}
其他功能
其他功能:
public String replace(char oldChar,char newChar)替换功能:使用指定的新的字符替换以前的字符
public String trim():删除前后两端空格
应用场景:trim(): 使用io(intput输入 Output输出)流进行 读写复制(文件内容在网络中传输)
文件内容前后有一些空字符出现,获取到文件内容之后,先去trim()去除两端空格
//public String replace(char oldChar,char newChar)
// 替换功能:使用指定的新的字符替换以前的字符
System.out.println(s.replace("CDE","XYZ"));
String s5=" DFGHJK ";
System.out.println("---------------------");
// public String trim():删除前后两端空格
System.out.println(s5);// DFGHJK
System.out.println(s5.trim());//DFGHJK
1.列举出Object类中常用的方法
public boolean equals(Object anoterObj):判断两个引用数据是否相等----底层原码this == anoterObj (几乎常见的类都会重写Object类的equals和hashCode(),两个对象的内容(成员信息)是否相等)
public String toString() //打印出对应的字符串形式,引用类型中,直接输出对象名称等价于调用了Object的toString-->打印出地址值 (建议所有子类都覆盖这个方法,结果是一个让人阅读的表达式!)
protected Object clone() throws CloneNOtSupportedException // 创建对象的副本 (克隆方法)
//前提要克隆,当前这个对象所在的类型必须实现一个 "标记接口" Cloneable接口,才能够完成克隆
public int hashCode() //哈希码值---->每一个不同的对象它的哈希码值不同的,可以理解为"地址值"---
-> //hash算法---返回值int类型的取值范围的值 (在引用数据类型中和equals一块要被重写)
2.String类的特点是什么?
String是一个不可变的,一旦被创建,其值不能被更改!(常量池中地址);
创建字符串格式:
String s = "字符串" ; //推荐
String s = new String("字符串") ;
String类特殊的引用类型,它作为方法形式参数,形式参是改变不会影响实际参数(和基本类型一致)
class Demo{
public static void main(String[] args){
String s = "helloworld" ;
System.out.println(s) ;
change(s) ;
System.out.println(s) ;//helloworld
}
public static void change(String str){//形式参数是一个String类型
str+= "javaee" ;
System.out.println(str) ;//helloworldjavaee
}
}
3.列举出String类的转换功能有哪些?(4个)
public char[] toCharArray() //将字符串转换成字符数组
public byte[] getBytes() //使用平台的默认字符集对字符串进行编码---字节数组
public static String valueOf(int/Object/double/float/boolean......)//将指定的类型转换String
public String toUppercase() //将字符串转换成大写
public String toLowercase() //将字符串转换成小写
...
4.列举出String类的获取功能(4个)
//截取功能
public String substring(int beginIndex,int endIndex)//从指定位置开始截取到endIndex-1处结束
public String substring(int beiginIndex)//从指定位置开始默认截取到末尾
//拆分
public String[] spilt(String regex)//将一个字符串通过指定分隔号拆分成字符串数组
//拼接功能
public String concat(String anotherString)//使用当前字符串和指定的字符串拼接成一个新的字符串,在末尾拼接
//获取字符串长度
public int length()
//面试题:
数组中有没有length(),String类中length(),在集合中有没有length()?
数组中length属性,
String类中有length(),获取字符串长度
集合中没有,size():获取集合中元素数
5.String类中两个字符串按照字典顺序如何比较的?
//1)获取两个字符串对应的字符数组的长度
//2)获取最小值 Math.min(长度1,长度2);
//3)将两个字符串使用字符数组表示
//4)定义统计变量 k=0
//5)循环 条件 k < 两个长度最小值
//6) 不断的通过k=0,1,2....取出对应字符数组中的元素,如果都一致,最终条件不满足了
如果条件满足:如果某一个字符不一致,直接返回return 第一个字符数组某一个字符-第二个字符数组某个字符
对应的ASCII码表的值相减
//7)return 长度1-长度2;
Strig s1 = "abc" ;
String s2 = "hel" ;
s1.compareTo(s2) ----> 'a' - 'h' = 97 -104
3.java.util.Date:日期类
重点:
java.util.Date日期格式 和String日期文本格式相互转换
String日期文本 2022/10/01 2022年10月1日 2022-10-01 "字符串日期"
4.Integer以及Character类的功能
Integer i = 整数;---->底层的Integer.valueOf(整数)
Integer类----内部类---IntegetCache:内部缓存区: 缓存池大小 -128~127
Character类提供
判断功能:判断一个字符是否为大写字母/小写字母/数字字符
5.一些其他类
System类
Math类
Random类
BigDecimal类:小数精确计算
Calendar日历类
6.什么是对象数组?
使用一个数组存储5个学生?,学生有姓名,年龄,让遍历数组---展示学生的信息
创建数组
数据类型[] 数组名称 = new 数据类型[数组长度] ;
Student[] students = new Student[5] ;
数组的弊端是长度固定,不支持长度可变的需求---->集合!
StringBuffer
StringBuffer:字符串缓冲区,线程安全的,支持可变的字符序列!
什么叫线程安全----->后面讲的多线程
线程安全----> 意味"同步"---->执行效率低!---"银行类的网站!"
线程不安全---->意味"不同步"---->执行效率高!----"论坛的网站!"---不安全--->"锁机制"来解决线程安全问题(多线程)
StringBuffer和StringBuilder的区别?
-
- 这两个类都是字符串缓冲区,都支持可变的字符序列,都有相同的功能 - 前者:使用在多线程环境里面,能够保证线程安全----意味着同步----->执行效率低 - 后者:是StringBuffer的简易替换,用于在单线程环境中,线程不安全---不同步---执行效率高! - 单线程使用StringBuilder:效率高(速度快)
StringBuffer的构造方法
public StringBuffer():
无参构造方法,里面空的字符序列,初始容量16个字符(默认容量足够大) -
public StringBuffer(String str):将字符串构造为StringBuffer类型,容量是大小:当前的里面的字符串长度+16
前两个构造方法使用居多!
public StringBuffer(int capacity):创建一个字符串缓冲区,指定容量大小
获取字符串缓冲区的长度 ---int length()
获取字符串缓冲区的容量---int capacity()
public class StringBufferDemo {
public static void main(String[] args) {
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
System.out.println("sb:"+sb) ;//sb:
System.out.println(sb.length());//0
System.out.println(sb.capacity());//16
System.out.println("-------------------------");
StringBuffer sb2 = new StringBuffer("hello") ;
System.out.println("sb2:"+sb2) ;//sb2:hello
System.out.println(sb2.length()) ;//5
System.out.println(sb2.capacity());//21
System.out.println("-----------------------------");
StringBuffer sb3 = new StringBuffer(50) ;
System.out.println(sb3) ;
sb3.append("hello").append('A') ;//6
System.out.println(sb3.length()) ;//50
System.out.println(sb3.capacity());
}
}
StringBuffer的添加 和删除功能添加:
添加:
public StringBuffer append(任意java类型)
将任意类型的元素追加在末尾字符缓冲区 返回值是字符串缓冲区本身
public StringBuffer insert(int offset,任意java类型)
在指定位置除前面加入新的序列
删除
public StringBuffer deleteCharAt(int index)
//开发中居多//在指定位置处删除指定的字符,返回字符串缓冲区本身
public StringBuffer delete(int start,int end)
从指定位置start处开始到end-1处的字符序列删除,返回值字符串缓冲区本身
开发中使用居多:追加功能以及删除 deletCharAt(int index)使用居多
例子:
package Test5;
public class Test5 {
public static void main(String[] args) {
StringBuffer sb=new StringBuffer();
//直接追加,可以任何类型数据
System.out.println(sb);
sb.append("hello");
sb.append("world");
sb.append("luffy");
sb.append("ship");
System.out.println(sb);//helloworldluffyship
System.out.println("-----------------");
//public StringBuffer insert(int offset,任意java类型)
// :在指定位置处的序列前面插入新的序列
sb.insert(5,"nami");
System.out.println(sb);
//hellonamiworldluffyship
System.out.println("-----------------");
// public StringBuffer deleteCharAt(int index):
// 在指定位置处删除指定的字符,返回字符串缓冲区本身
sb.deleteCharAt(5);
System.out.println(sb);
//helloamiworldluffyship
// public StringBuffer delete(int start,int end):从指定位置start处开始到end-1处的字符序列删除,
// * 返回值字符串缓冲区本身
System.out.println("-----------------");
sb.delete(5,6);
System.out.println(sb);
//hellomiworldluffyshipa
}
}
面试题:
String和StringBuffer的区别?
String特点:字符串是一个常量,一旦被创建,其值不能被更改
String作为形式参数,形参的改变不会影响实际参数;
而除过String这个引用类型之外,形式参数的改变直接影响实际参数!
StringBuffer特点:字符串缓冲区支持可变的字符串,线程安全,执行效率低!
package Test2;
public class StringBufferDemo2 {
public static void main(String[] args) {
String s="hello";
System.out.println(s);//hello
change(s);//调用change方法 helloworldjavaee
System.out.println(s);//hello
StringBuffer sb=new StringBuffer("456");
System.out.println(sb);//456
change(sb);//456123
System.out.println(sb);//456123
}
private static void change(StringBuffer sb) {
sb.append("123");
System.out.println(sb);
}
private static void change(String s) {
s+="worldjavaee";
System.out.println(s);
}
}
StringBuffer的特有功能:
public StringBuffer reverse() :字符串缓冲区反转功能,将字符串缓冲区中所有的字符序列反转!
例子:自己编的版本
package Test6;
public class Test6_2 {
public static void main(String[] args) {
String A = "WOZHENDEHAOXAINGSHUJIAO ";
StringBuffer sb = new StringBuffer(A);
sb.reverse();
System.out.println(sb);
//OAIJUHSGNIAXOAHEDNEHZOW
}
}
例子:老师讲解版本
package Test6;
import java.util.Scanner;
public class Test6 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入一个字符串");
String s= sc.nextLine();
String reverse = reverse(s);
System.out.println(reverse);
}
public static String reverse(String s){
return new StringBuffer(s).reverse().toString();
}
}
String和StringBuffer相互转换
在开发中,需要将A类型转换成B类型,因为需要使用B类型的功能
但是结果可能需要A类型,又需要将B类型转换A类型!
String<---->StringBuffer相互转换 (重点)
方式1 StringBuffer的有参构造方法
方式2 StringBuffer的无参构造方法+append(String str)
public class StringBufferTest {
public static void main(String[] args) {
//String---->StringBuffer
String s = "hello" ;
//方式1)可以通过StringBuffer的有参构造方法
//StringBuffer(String str)
//创建一个字符串缓冲
StringBuffer sb = new StringBuffer(s) ;
System.out.println(sb) ;
System.out.println("-------------------------") ;
//方式2:通过StringBuffer的无参构造方法+append(String str)
StringBuffer sb2 = new StringBuffer() ;
sb2.append(s) ;
System.out.println(sb2);
System.out.println("---------------StringBuffer-->String------------------");
//有一个字符串缓冲区--->里面存在字符序列
StringBuffer buffer = new StringBuffer("100") ;
//方式1) -->public String toString()
String str = buffer.toString();
System.out.println(str) ;
System.out.println("----------------------------------------") ;
//方式2:String类的构造方法
//public String(StringBuffer buffer)
String str2 = new String(buffer) ;
System.out.println(str2) ;
}
}
例子自己:
package Test7;
//String和StringBuffer相互转换
public class Test7 {
public static void main(String[] args) {
//String-->StringBuffer
方式1)可以通过StringBuffer的有参构造方法
String s="ONEPIECETOP1";
StringBuffer sb=new StringBuffer(s);
System.out.println(sb);
System.out.println("---------------------");
//方式2:通过StringBuffer的无参构造方法+append(String str)
StringBuffer sb2=new StringBuffer();
sb2.append("QWERADS");
System.out.println(sb2);
System.out.println("---------------------");
//StringBuffer-->String
//方式1) -->public String toString()
StringBuffer sb3=new StringBuffer("200");
String s1 = sb3.toString();
System.out.println(s1);
//方式2:String类的构造方法
//public String(StringBuffer buffer)
String s2 = new String(sb3);
System.out.println(s2);
}
}
StringBuffer替换和截取功能
StringBuffer其他功能:
替换功能
public StringBuffer replace(int start,int end,String str)
使用指定的字符串str从指定位置开始到end-1处进行替换,返回该字符串缓冲区本身
截取功能
public String substring(int start)
从指定位置开始截取,默认截取到末尾,返回被截取后的字符串
public String substring(int start,int end)
从指定位置开始截取到指定位置end-1处,返回被截取后的字符串
public class StringBufferDemo4 {
public static void main(String[] args) {
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
sb.append("hello") ;
sb.append("world") ;
sb.append("javaee") ;
System.out.println(sb) ;
//public StringBuffer replace(int start,int end,String str)
sb.replace(5,10,"高圆圆") ;
System.out.println(sb) ;
System.out.println("-------------------------------------");
//String str = sb.substring(5);
//System.out.println(str);
System.out.println(sb.substring(5,8));
}
}
例子自己:
package Test8;
public class Test8 {
public static void main(String[] args) {
StringBuffer sb=new StringBuffer();
sb.append("HELLO");
sb.append("nihao");
sb.append("432");
sb.append("mcn");
System.out.println(sb);//HELLOnihao432mcn
System.out.println("----------------");
sb.replace(2,2,"sbs");
System.out.println(sb);//HEsbsLLOnihao432mcn
System.out.println("----------------");
String d = sb.substring(2);
String d2 = sb.substring(2, 5);
System.out.println(d);//sbsLLOnihao432mcn
System.out.println(d2);//sbs
}
}
Integer
Integer : int类型的包装类类型
提供了一些功能: 快速得出十进制对应的进制的方法(静态方法)
快速得出int类型的取值范围
四类八种基本数据类型都会自动提升对应的引用类型
jdk5后的新特性:自动拆装箱
拆箱--这些包装类型降为对应的基本数据类型
装箱--这些基本数据类型升为对应的包装类型
转换对应进制例子
例子
public class IntegerDemo {
public static void main(String[] args) {
//public static String toOctalString(int i) 以字符串形式体现八进制
//public static String toHexString(int i) 以字符串形式体现16进制
//public static String toBinaryString(int i)以字符串形式体现的2进制
System.out.println(Integer.toBinaryString(100));//二进制
System.out.println(Integer.toOctalString(100));//八进制
System.out.println(Integer.toHexString(100));
//十六进制
System.out.println("-------------------------------------");
//public static final int MAX_VALUE:常量:获取int的最大值
//public static final int MIN_VALUE:常量:获取int的最小值
System.out.println(Integer.MIN_VALUE) ;
System.out.println(Integer.MAX_VALUE) ;
}
}
例子自己:
package Test9;
//转换对应进制例子
public class Test9 {
public static void main(String[] args) {
System.out.println(Integer.toBinaryString(200));//二进制
System.out.println(Integer.toHexString(200));//十六进制
System.out.println(Integer.toOctalString(200));//八进制
System.out.println("-------------------------------");
System.out.println(Integer.MAX_VALUE);//获取int的最大值
System.out.println(Integer.MIN_VALUE);//获取int的最小值
}
}
这些基本类型都可以和String相互转换 是中间桥梁 对应的基本类型的包装类型
byte | Byte |
---|---|
short | Short |
int | Integer(特殊) |
Long | Long |
float | Float |
double | Double |
char | Character(特殊) |
boolean | Boolean |
Integer的构造方法
Integer类的构造方法:
public Integer(int value):创建一个Integer实例,里面包含的int类型的值
public Integer(String s) throws NumberFormatException: 将数字字符串转换成Integer的实例
可能会出现数字格式化异常(字符串如果不是数字字符串,就会出现这个异常)
例子
public class IntegerDemo2 {
public static void main(String[] args) {
//创建一个Integer实例
//public Integer(int value):创建一个Integer实例,里面包含的int类型的值
int a = 100 ;
Integer i = new Integer(a) ;
System.out.println(i) ;
System.out.println("-----------------------------") ;
// public Integer(String s) throws NumberFormatException:
//Integer i2 = new Integer("hello") ;//NumberFormatException:数字格式化异常
Integer i2 = new Integer("50") ;
System.out.println(i2);
}
}
Integer是int类型的包装类类型,它里面的特点
Integer:
将int类型赋值给Integer变量 这种格式,执行底层方式valueOf(int i)
public static Integer valueOf(int i) {
如果i的值在-128~127之间,直接从内部类--->IntegerCache缓存去中取数据
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
// cache属性:Integer cache[] 长度 =i+128
eturn new Integer(i); //如果上if不成立,重新开辟新的空间创建Integer实例
}
int赋值给Integer变量
例子
public class IntegerTest {
public static void main(String[] args) {
Integer i1 = 127 ;
Integer i2 = 127 ;
System.out.println(i1==i2) ; //true
System.out.println(i1.equals(i2)) ; //true比较内容
Integer i3 = 127 ;
Integer i4 = new Integer(127) ;
System.out.println(i3==i4) ; //false
System.out.println(i3.equals(i4)) ;//true
Integer i5 = 128 ; //new Integer(128) ;//超过范围了就要开辟新的地址值
Integer i6 = 128 ;//new Integer(128);//超过范围了
System.out.println(i5==i6) ; //false
System.out.println(i5.equals(i6)) ;//true
Integer i7 = new Integer(128) ;
Integer i8 = new Integer(128) ;
System.out.println(i7==i8) ; //false//比较的是地址值
System.out.println(i7.equals(i8)) ;//true//比较的是内容
}
}
ctrl+alt+m 抽取的意思
System三字段
java.lang.System:不能实例化:提供了静态字段(静态变量)
-
- public static final PrintStream out :标准 打印输出流 - public static final PrintStream err 标准错误输出流 - public static final InputStream in 标准输入流 Stream:流
例子
package SystemDemo1;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class Test6 {
public static void main(String[] args) throws IOException {
System.out.println("标准打印流");
System.out.println("--------------");
PrintStream ps=System.out;
//PrintStream提供各种打印的方法print(不换行任何类型数据)/prinln("换行打印任何类型数据")
ps.println(100);
ps.print(false);
ps.print('A');
ps.println();//换行作用
ps.write("hello".getBytes(StandardCharsets.UTF_8));
ps.println();
System.out.println("--------------");
//public static final PrintStream err 标准错误输出流
PrintStream ps2=System.err;
ps2.print("错误输出流打印数据");//输出的字体颜色是红色
System.out.println("--------------");
//public static final InputStream in 标准输入流 :读数据
InputStream is=System.in;
Scanner sc=new Scanner(is);
System.out.println("输入数据");
int a=sc.nextInt();
System.out.println(a);
}
}
System类常用的成员方法:
-
- public static long currentTimeMillis() 计算当前系统时间毫秒值 (很少单独用) - 用来计算当前某个程序的时间复杂度(运行效率) * - public static void gc() 收到开启垃圾回收器 ---会调用finalize(),回收没有更多引用的对象 - public static void exit(int status): 参数为0:终止jvm - public static void arraycopy( - Object src, //原对象 - int srcPos, //原对象中的某个位置 - Object dest, //目标对象 - int destPos, //目标对象的某个位置 - int length) //指定的长度
例子
package SystemDemo2; import java.util.Arrays; public class Test7 { public static void main(String[] args) { long l=System.currentTimeMillis(); System.out.println(l);//计算当前系统时间毫秒值 //System.exit(0);//正常终止JVM System.out.println("------------------"); int [] arr={23,43,21,2,56}; int [] arr2={98,43,34,3}; System.out.println("复制前"); System.out.println(Arrays.toString(arr)); System.out.println(Arrays.toString(arr2)); System.arraycopy(arr,1,arr2,0,3); //意思就是从第一个数组的第1个(从0开始计数和数组一样)开始复制过去三个元素给数组2,并且从数组2 的第0位开始 System.out.println(Arrays.toString(arr)); System.out.println(Arrays.toString(arr2)); } }
Random
java.util.Random:伪随机数生成器 可以产生随机数 比Math.random()麻烦
两个构造方法:
public Random() :无参构造方法(推荐)
public Random(long seed):有参构造,创建一个指定long类型的变量的随机数生成器
两个成员方法:
public int nextInt(): 产生伪随机数在,取值是int类型 的范围内
public int nextInt(int n):产生0-n之间的随机数(推荐)
例子自己
package RandomDemo1;
import java.util.Random;
public class Test2 {
public static void main(String[] args) {
Random r2=new Random();
for(int x=0;x<3;x++) {//你要取的随机数的个数
int i = r2.nextInt(20);
//bound 意思是你要取的随机数的范围是20以内
//public int nextInt(int n):产生0-n之间的随机数(推荐)
System.out.println(i);
}
}
}
package RandomDemo1;
import java.util.Random;
public class Test1 {
public static void main(String[] args) {
Random r=new Random(100);
for(int a=0;a<10;a++){
int x=r.nextInt(200);
System.out.println(x);
//获取100开始的十个随机数
}
Random r2=new Random(300);
System.out.println(r2);
}
}
java.util.calendar
基本介绍
-
- java.util.Calendar:日历类(抽象类) - 提供了获取年,年中的月,月中的日期,小时,小时分钟数,分钟中的秒数都可以获取到 - 如果有一个类是抽象类,可以直接new子类,或者是它提供了一些静态方法----> - 完成了一些事情,创建子类对象,返回值是当前抽象类的本身 - 成员方法: - public static Calendar getInstance() 创建日历对象 - public int get(int field):通过日历对象获取日历中的字段值 - 参数:Calendar中提供的一些静态字段 - public static final int YEAR:年份 - public static final int DAY_OF_MONTH/public static final int DATE:月中的日期 - public static final int MONTH:月份 - public abstract void add(int field,int amount):给指定的日历字段值添加或者减去时间偏移量
例子
package Calendar;
import java.util.Calendar;
public class Test5 {
public static void main(String[] args) {
Calendar c= Calendar.getInstance() ;
System.out.println(c);
System.out.println("-------------");
int year=c.get(Calendar.YEAR);
int mouth=c.get(Calendar.MONTH);默认计算0-11 所以月份打印的时候要+1
int date=c.get(Calendar.DAY_OF_MONTH);
System.out.println(year+"-"+(mouth+1)+"-"+date);//要加"-"不然会把年月日相加
System.out.println("-------------");
//5年前的10天前
c.add(Calendar.YEAR,-5);
c.add(Calendar.DAY_OF_MONTH,-10);
int year2=c.get(Calendar.YEAR);
int mouth2=c.get(Calendar.MONTH);
int date2=c.get(Calendar.DAY_OF_MONTH);
System.out.println(year2+"-"+(mouth2+1)+"-"+date2);
}
}
java.util.Date
基本介绍
java.util.Date:表单特定的日期时间,还允许格式化和解析日期字符串
构造方法:
public Date():创建当前日期对象:获取当前系统日期时间
public Date(long date):里面传入long类型的时间毫秒值,获取的表示从标准基准时间(称为“时代”)即1970年1月1日00:00:00 GMT起的指定毫秒数
成员方法:
public long getTime():将Date对象转换成long类型时间毫秒值
public void setTime(long time):设置日期时间,参数时间毫秒值
SimpleDateFormat
-
- java.util.Date重点如何和String日期文本相互转换! - 他们之间要进行转换需要使用类DateFormat - DateFormat是日期/时间格式化子类的抽象类,它以语言无关的方式格式化和分析日期或时间 - 它具体的子类:SimpleDateFormat是一个具体的类,允许格式化(日期文本),解析(文本日期) 构造方法: - public SimpleDateFormat(String pattern):参数是日期模式 "yyyy-MM-dd" - pattern的组成: - y:表示年份中某个值----->yyyy 表示年 "1996/2023/..." - M:表示年中的月份------>MM 表示月:七月-->"07" 十月 -->"10" - d:表示月中的日期值----->dd 表示 "01","11","31".. - 成员方法 - 将Date---->String:格式化 public final String format(Date date) - 将String日期---->Date:解析 - public Date parse(String source)throws ParseException - 定义工具类DateUtils 日期工具类---构造方法私有外,提供静态功能 - 将下面Date---->String格式化---定义功能完成 - 将String---->Date解析---定义功能完成
例子
package DateDemo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test3 {
public static void main(String[] args) throws ParseException {
Date d=new Date();
System.out.println(d);
//Thu Mar 16 14:14:12 CST 2023
System.out.println("-------------");
long time=d.getTime();
System.out.println(time);
//1678950717857毫秒
System.out.println("-------------");
//date转String
SimpleDateFormat sdf=new SimpleDateFormat("YYYY年MM月dd日 HH:mm:ss");
String str = sdf.format(d);
System.out.println(str);
//2023年03月16日 15:11:57
System.out.println("-------------");
//String转date
String ss="2023-8-8";
SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd");
Date d2=sdf2.parse(ss);
System.out.println(d2);
//Tue Aug 08 00:00:00 CST 2023
}
}
//注意模板pattern中的数据大小写
集合(Collection)
集合是一个容器 可存储不同类型的元素,但必须是引用类型,集合长度可变;集合只能存储引用类型
集合和数组区别
集合和数组区别
1)长度
数组的长度固定
集合的长度可变
2)存储数据的区别
数组:可以存储基本数据类型也可以存储引用数据类型
集合只能存储引用数据类型
3)存储元素的区别
数组:存储的元素数据类型必须一致
集合:如果没有明确<泛型>,可以存储任意的引用类型包括Object
Collection:单例集合顶层次的根接口,不能new,没有直接子实现类,通过他子接口的子实现类来实例化!
泛型<>:集合里面创建的时候,如果不带泛型可能程序安全问题;带了泛型,模拟数组创建的时候,明确了数据类型
element
Tybe
Key键
Value
基本功能:
集合转数组
例子: String[] str = i.toArray(new String[0]);
带参的toArray方法
添加元素
boolean add(E e):添加元素
删除元素
boolean remove(Object o):删除指定的元素
void clear():暴力删除:清空集合
判断功能
boolean contains(Object o):是否包含指定的元素
boolean isEmpty():判断集合是否为空
例子
package CollectionDemo1;
import java.util.ArrayList;
import java.util.Collection;
public class Test9 {
public static void main(String[] args) {
Collection<String>c=new ArrayList<>();//Collection不能直接new 通过多态实现他的子类接口
System.out.println(c);//[]
//boolean add(E e):添加元素
c.add("你好");
c.add("世界");
c.add("再见");
System.out.println(c);//[你好, 世界, 再见]
System.out.println("----------------");
//boolean remove(Object o):删除指定的元素
System.out.println(c.remove("你好"));//true
System.out.println(c);//[世界, 再见]
System.out.println("----------------");
//boolean contains(Object o):是否包含指定的元素
//boolean isEmpty():判断集合是否为空
System.out.println(c.contains("世界"));//true 因为集合确实存在"世界"这个元素
System.out.println(c.isEmpty());//false 因为集合不为空
System.out.println("----------------");
//c.clear();暴力删除
c.clear();
System.out.println(c);//[]删除了所有元素
}
}
迭代器
Iterator<E> iterator():Collection专有迭代器(遍历集合) (过渡)
Iterator迭代器接口:
boolean hasNext(): 判断迭代器里面是否下一个可以遍历的元素
E next():获取迭代器的下一个元素 (和迭代器中的类型一致)
开发中---集合遍历---->都用jdk5以后新特性:增强for循环 代替上面迭代器
Collection集合高级功能:
Object[] toArray():集合的传统方式遍历 将集合转换成对象数组(以后不会用的)
例子老师:
public class CollectionDemo2 {
public static void main(String[] args) {
//使用Collection存储String字符串并进行遍历---使用Collection迭代器
Collection<String> c = new ArrayList<>() ;
//添加String
c.add("android") ;
c.add("JavaEE") ;
c.add("mysql") ;
c.add("hadoop") ;
//c.add(100) ;
//获取Collection的迭代器
//Iterator<E> iterator()
Iterator<String> it = c.iterator();
//E next() //E---类型需要和泛型的类型一致的
/*//第一次取
Object object = it.next();
String s = (String) object;
System.out.println(s);
//第二次取
Object object2 = it.next();
System.out.println((String)object2);
//第三次取
Object object3 = it.next();
System.out.println((String)object3);*/
//第一次取
/* if(it.hasNext()){
String next = it.next();
System.out.println(next);
}
//第二次取
if(it.hasNext()){
System.out.println(it.next());
}
//第三次取
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
//第四次取
System.out.println(it.next());
}
if(it.hasNext()){
//第五次取
System.out.println(it.next());
}*/
//while循环
while(it.hasNext()){
String s = it.next();
System.out.println(s+"---"+s.length());
}
//第五次取
//System.out.println(it.next());//NoSuchElementException:没有元素了
}
}
迭代器的原理
师说:
迭代器:帮助我们做集合遍历的工具。
Collection集合元素的通用获取方式: 在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来;继续再判断,如果还有就再取出来。一直到把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。集合中把这种取元素的方式描述在Iterator接口中。
修饰语和类型 | 方法 | 描述 |
---|---|---|
boolean | hasNext() | 判断集合中还有没有可以被取出的元素,如果有返回true |
E | next() | 取出集合中的下一个元素 |
增强for替代迭代器
Jdk5新特性:
<泛型>,增强for,可变参数,静态导入(导入到方法级别:方法必须静态)...
增强for:
是在集合/数组中存储的引用类型中使用居多,代替集合迭代器的,简化书写代码
for(集合中存储的数据类型 变量名:集合对象){
使用这个变量名即可
}
注意
要使用增强for遍历集合,集合对象不能null;
防止空指针异常,在使用增强for之前,对集合进行非空判断
Collection<Student>,使用ArrayList具体的子实现类,保证Student对象唯一!
去重(学生的成员信息相同,则是同一个人)
ArrayList集合的contains()方法依赖于Object的equals方法,底层实现的"==",比较的是地址值是否相同,下面9个学生都new出来的
地址值不相同,都添加到集合中
在ArrayList存储自定义类型,要保证元素唯一,必须重写equals和hashCode方法
例子师说:
public class Test3 {
public static void main(String[] args) {
Collection<Student> c = new ArrayList<>() ;
//创建学生对象
Student s1 = new Student("曹操",45) ;
Student s2 = new Student("周瑜",20) ;
Student s3 = new Student("刘备",35) ;
Student s4 = new Student("关羽",32) ;
Student s5 = new Student("张飞",30) ;
Student s6 = new Student("张飞",30) ;
Student s7 = new Student("高圆圆",44) ;
Student s8 = new Student("高圆圆",44) ;
Student s9 = new Student("高圆圆",35) ;
//添加
c.add(s1) ;
c.add(s2) ;
c.add(s3) ;
c.add(s4) ;
c.add(s5) ;
c.add(s6) ;
c.add(s7) ;
c.add(s8) ;
c.add(s9) ;
//新建空的集合
Collection<Student> newColl = new ArrayList<>() ;
//遍历以前的集合
for(Student s:c){
//新集合中判断,如果包含这个学生对象,就添加新集合中
if(!newColl.contains(s)){
newColl.add(s) ;
}
}
//遍历新集合
for(Student student:newColl){
System.out.println(student.getName()+"---"+student.getAge());
}
}
}
并发修改异常
需求:
有一个Collection集合,存储一些不重复的String元素,如果现在里面有"world",需要给集合中添加一个新的"JavaEE"元素!
分析:
1)创建Collection,模拟存储一些字符串,里面就包含"world"
2)获取Collection集合迭代器,遍历元素,
3)判断,如果这里面存在"world",然后添加"JavaEE"
出现了异常"ConcurrentModificationException":并发修改异常
什么叫并发:在某个时间点上同时进行!
在集合这块出现ConcurrentModificationException原因:
当使用迭代器去遍历元素的时候,同时不能使用集合对象去操作(修改或添加...)元素,就会出现这个异常!
因为,迭代器在遍历元素的时候,集合添加一个新的元素,迭代器不知道!
解决方案:
Collection没有直接操作----->子接口List特有功能(ListIterator:列表迭代器/List集合普通for+size()+get(int index))
1)集合遍历,集合添加
2)迭代器遍历,迭代器遍历
解决办法1:List的列表迭代器解决
import java.util.*;
//"ConcurrentModificationException":并发修改异常
用List的迭代器
public class Test7 {
public static void main(String[] args) {
// Collection<String>cs=new ArrayList<>();//这种 不行
List<String>ls=new ArrayList<>();
ls.add("并发");
ls.add("修改");
ls.add("异常");
ls.add("ConcurrentModificationException");
ls.add("解决办法");
ListIterator<String>is=ls.listIterator();
//使用集合迭代器添加集合元素
while(is.hasNext()){
String s=is.next();
if(s.equals("ConcurrentModificationException")){
is.add("新来的");
}
}
System.out.println(ls);
}
}
//[并发, 修改, 异常, ConcurrentModificationException, 新来的, 解决办法]
解决办法2:List中增强For解决
package ConcurrentModificationException;
import java.util.ArrayList;
import java.util.List;
public class Test8 {
public static void main(String[] args) {
// Collection<String>cs=new ArrayList<>();//这种 不行
List<String> ls = new ArrayList<>();
ls.add("并发");
ls.add("修改");
ls.add("异常");
ls.add("ConcurrentModificationException");
ls.add("解决办法");
for(int i=0;i<ls.size();i++){
String s=ls.get(i);
if(s.equals("ConcurrentModificationException")){
ls.add("New");
}
}
System.out.println(ls);
}
}
去重方法
package Test_CollectionIteratorQuChong;
//去重
import java.util.ArrayList;
import java.util.Collection;
public class Test3 {
public static void main(String[] args) {
Collection<String>S=new ArrayList<>();
S.add("hello");
S.add("hello");
S.add("big");
S.add("hello");
S.add("world");
S.add("size");
S.add("world");
Collection<String>S2= new ArrayList<>();
for (String ss : S) {
if(!S2.contains(ss)){//contains是判断是否有这个元素的方法
S2.add(ss);
}
}
for (String ss : S2) {
System.out.println(ss);
}
}
}
List集合:
特点–List集合是Collection集合的子接口,它的集合遍历方式
元素有序(存储和取出一致) 元素可以重复
1) Collection的Object[] toArray()
2)Collectionde Iterator iterator()
3)使用size()+存储的数据类型get(int index) 通过角标获取元素内容:普通迭代器
4)ListIterator<E>listIterator()List集合专有遍历方式:列表迭代器
5)增强for(推荐!)
例子:
需求:
* 三个Java班级:每一个班级看成ArrayList
* 三个班级组成一个大的集合ArrayList<ArrayList<Student>>,
* 第一个班级存储
* 高圆圆 22
* 赵又廷 25
* 第二个班级存储
* 张三丰 50
* 令狐冲 35
* 第三个班级存储
* 孙悟空 32
* 唐僧 40
*
* 去遍历大的集合
ArrayList<ArrayList<Student>>,打印学生信息
package Test4;
import java.util.ArrayList;
class Student{
private String name;
private int age;
public Student(){}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test4 {
public static void main(String[] args) {
ArrayList<ArrayList<Student>> bigArray=new ArrayList<>();
ArrayList<Student> s = new ArrayList<>();
Student s1 = new Student("高圆圆", 22);
Student s2 = new Student("赵又廷", 25);
s.add(s1);
s.add(s2);
bigArray.add(s);
ArrayList<Student> ss = new ArrayList<>();
Student s3 = new Student("张三丰", 50);
Student s4 = new Student("令狐冲", 35);
ss.add(s3);
ss.add(s4);
bigArray.add(ss);
ArrayList<Student> sss = new ArrayList<>();
Student s5 = new Student("孙悟空", 32);
Student s6 = new Student("唐僧", 40);
sss.add(s5);
sss.add(s6);
bigArray.add(sss);
//遍历
System.out.println("学生信息是:\t");
System.out.println("姓名\t\t年龄");
for(ArrayList<Student> array:bigArray){
for(Student student:array){
System.out.println(student.getName()+" \t"+student.getAge());
}
}
}
}
遍历方式例子
public class ListDemo {
public static void main(String[] args) {
//创建List集合
List<String> list = new ArrayList<>() ;
list.add("hello") ;
list.add("world") ;
list.add("JavaEE") ;
list.add("android") ;
list.add("ios") ;
//3)4)5)特有方式
//使用size()+ 存储的数据类型 get(int index)通过角标获取元素内容 :普通for循环格式
for(int x = 0 ; x < list.size() ; x++){
//通过x角标值获取元素内容
String s = list.get(x);
System.out.println(s);
}
System.out.println("--------------------------------------------------") ;
//ListIterator<E> listIterator()List集合的专有遍历方式 :列表迭代器
ListIterator<String> lit = list.listIterator();//获取列表迭代器
//ListIterator--->接口提供一些方法
//boolean hasNext():判断是否有下个元素
//E next():获取下一个元素
while(lit.hasNext()){
String s = lit.next();
System.out.println(s);
}
System.out.println("--------------------------------");
//列表迭代器提供了一些功能,进行逆序遍历(前提必须有上面的正向遍历)
//boolean hasPrevious():判断是有上一个元素
//E previous():获取上一个元素
while(lit.hasPrevious()){
String previous = lit.previous();
System.out.println(previous);
}
System.out.println("---------------------------------------------------") ;
//增强for (推荐)
for(String s:list){
System.out.println(s) ;
}
}
}
List三个子实现类的特点
实际需求:单线程使用List完成一些事情,没有明确规定具体使用哪个实现类,默认使用ArrayList
默认ArrayList
底层数据结构是数组--查询快,增删慢!(数组,通过整数索引查询)
元素查找:顺序查找,二分搜索,哈希查找
线程角度:
线程不安全的类,不同步但是效率高!
底层扩容机制1.5倍
普普通通的遍历
import java.util.ArrayList;
public class Test6 {
public static void main(String[] args) {
ArrayList<String> as=new ArrayList<>();
as.add("这是");
as.add("ArrayList");
as.add("的例子");
as.add("遍历");
for(String s2:as){
System.out.print(s2);
}
}
}
并发修改异常的解决.
使用List集合解决并发修改异常
List有特有方式:
size()获取集合长度 结合 Object get(int index)通过索引值获取对应的内容
特有添加元素的方式:
void add(int index,E element):在指定位置处,添加指定的元素!
使用Collection<String>,如果Collection集合中存储有"world"元素,给集合中新添加一个元素--->
出现ConcurrentModificationException 出现并发修改异常的原因:使用迭代器去遍历元素的时候,不能同时集合操作元素;
解决方案:
1)集合遍历,集合添加
2)迭代器遍历,迭代器添加元素
List继承Collection--->Iterator是Collection的专有迭代器,没有提供添加功能,而
List集合专有遍历方式ListIterator:列表迭代器
列表迭代器解决
import java.util.*;
//"ConcurrentModificationException":并发修改异常
用List的迭代器
public class Test7 {
public static void main(String[] args) {
// Collection<String>cs=new ArrayList<>();//这种 不行
List<String>ls=new ArrayList<>();
ls.add("并发");
ls.add("修改");
ls.add("异常");
ls.add("ConcurrentModificationException");
ls.add("解决办法");
ListIterator<String>is=ls.listIterator();
//使用集合迭代器添加集合元素
while(is.hasNext()){
String s=is.next();
if(s.equals("ConcurrentModificationException")){
is.add("新来的");
}
}
System.out.println(ls);
//使用集合迭代器删除集合元素
while(is.hasNext()){
String s=is.next();
if(s.equals("ConcurrentModificationException")){
is.remove();
}
}
System.out.println(ls);
//使用集合迭代器修改集合元素
while(is.hasNext()){
String s=is.next();
if(s.equals("ConcurrentModificationException")){
is.remove();
is.add("修改的");
}
}
System.out.println(ls);
}
}
//[并发, 修改, 异常, ConcurrentModificationException, 新来的, 解决办法]
List增强For解决
package ConcurrentModificationException;
import java.util.ArrayList;
import java.util.List;
public class Test8 {
public static void main(String[] args) {
// Collection<String>cs=new ArrayList<>();//这种 不行
List<String> ls = new ArrayList<>();
ls.add("并发");
ls.add("修改");
ls.add("异常");
ls.add("ConcurrentModificationException");
ls.add("解决办法");
//普通for循环增加元素
for(int i=0;i<ls.size();i++){
String s=ls.get(i);
if(s.equals("ConcurrentModificationException")){
ls.add("New");
}
}
System.out.println(ls);
//普通for循环删除元素
for(int i=0;i<ls.size();i++){
String s=ls.get(i);
if(s.equals("ConcurrentModificationException")){
ls.remove(s);
i--;
}
}
//普通for循环修改元素
for(int i=0;i<ls.size();i++){
String s=ls.get(i);
if(s.equals("ConcurrentModificationException")){
ls.remove(s);
ls.add("新修改的");
}
}
}
}
Vector
底层数据结构是数组--查询快,增删慢!
线程角度:
线程安全的类,同步但是效率低!多线程环境下使用居多,单线程环境使用ArrayList
特有功能
遍历方式:Collection的Object[] toArray()
Collection的Iterator iterator()
List接口提供的 size()+get(int index)
List接口提供的ListIterator listiterator()
特有遍历方式
public Enumeration<E> elements()--->相当于集合的迭代器
Enumeration接口:枚举组件
boolean hasMoreElements()---->相当于boolean hasNext()
E nextElement()---->相当于E next()
public E elementAt(int index)--->相当于List的get(int index)+size方法相结合
增强for
添加:
public void addElement(E obj)--->相当于List的add()
public E elementAt(int index)--->相当于List的get(int index)
例子
import java.util.Enumeration;
import java.util.Vector;
public class VectorDemo {
public static void main(String[] args) {
//创建Vector集合
Vector<String> v = new Vector<>() ;
//public void addElement(E obj)--->相当于List的add()
v.addElement("hello");
v.addElement("world");
v.addElement("javaee");
v.addElement("mysql");
// 遍历
//public E elementAt(int index)--->相当于List的get(int index)+size方法相结合
for(int x = 0 ; x < v.size() ; x++){
String s = v.elementAt(x);
System.out.println(s);
}
System.out.println("----------------------------------------") ;
/**
* public Enumeration<E> elements()--->相当于集合的迭代器
* Enumeration接口:枚举组件
* boolean hasMoreElements()---->相当于boolean hasNext()
* E nextElement() ---->相当于E next()
*/
/* for(Enumeration<String> en = v.elements(); en.hasMoreElements();){
System.out.println(en.nextElement());
}*/
Enumeration<String> en = v.elements() ;
while(en.hasMoreElements()){
String s = en.nextElement();
System.out.println(s);
}
System.out.println("-----------------------------------") ;
for(String s:v){
System.out.println(s);
}
}
}
LinkedList
底层数据是链表,查询慢,增删快
线程角度:
线程不安全!不同步,效率高!
特有功能
LinkedList的特有方法:
public void addFirst(E e) :在链表开头插入元素
public void addLast(E e) :在链表末尾插入元素
public E removeFirst(): 删除链表开头的第一个元素并返回该元素
public E removeLast()从此列表中删除并返回最后一个元素。
public E getFirst():返回链表头元素
public E getLast():返回链表链尾元素
例子
public class LinkedListDemo {
public static void main(String[] args) {
//创建LinkedList集合
LinkedList<String> link = new LinkedList<>() ;
//添加元素
link.addFirst("hello") ;
link.addFirst("world") ;
link.addFirst("javaee") ;
/* for(String s:link){
System.out.println(s);
}*/
System.out.println(link);
//删除
System.out.println(link.removeFirst()) ;
System.out.println(link);
//获取
System.out.println(link.getFirst());
System.out.println(link.getLast());
}
}
小作业
需求:
利用LinkedList模拟栈的结构特点,先进后出
自定义类--->里面使用到LinkedList的特有功能
方法add()--->linkedList的addFirst()
get()--->获取元素: LinkedList的removeFirst()删除并返回
自定义一个方法isEmpty()--->判断LinkedList是否为空
在定义一个测试类---完成上面类的功能测试
Set集合:
元素唯一的,无序(存储和取出不一致),不能保证迭代次序,但可以是唯一!
HashSet<E> : 存储和取出,保证元素唯一!
---底层是HashMap实例(哈希表)
TreeSet<E> : 存储和取出,同时需要进行排序的取出!
---底层是依赖TreeMap实例(红黑树结构)
Set的两个子实现类
HashSet
使用HashSet存储一些学生(姓名,年龄),让你保证学生对象唯一!
自定义类型必须重写HashCode和equals方法,保证自定义类的对象唯一!
例子
public class HashSetDemo {
public static void main(String[] args) {
//创建HashSet集合对象
HashSet<String> hs = new HashSet<>() ;
hs.add("hello") ;
//System.out.println("hello".hashCode());
hs.add("hello") ;
hs.add("hello") ;
hs.add("world") ;
hs.add("world") ;
hs.add("world") ;
hs.add("JavaEE") ;
hs.add("JavaEE") ;
//遍历
for(String s:hs){
System.out.println(s);
}
}
}
例子2
public class Student {
private String name ;
private int age ;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name.equals(student.name);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
public class HashSetTest {
public static void main(String[] args) {
HashSet<Student> hs = new HashSet<>() ;
//创建学生对象
Student s1 = new Student("高圆圆",44) ;
Student s2 = new Student("高圆圆",44) ;
Student s3 = new Student("高圆圆",35) ;
Student s4 = new Student("文章",35) ;
Student s5 = new Student("文章",35) ;
Student s6 = new Student("王宝强",30) ;
Student s7 = new Student("王宝强",30) ;
//添加
hs.add(s1) ;
hs.add(s2) ;
hs.add(s3) ;
hs.add(s4) ;
hs.add(s5) ;
hs.add(s6) ;
hs.add(s7) ;
//遍历
for(Student s:hs){
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
//可以自动去重
TreeSet
两种排序方式
1自然排序
自然排序:
TreeSet<E>() 无参构造方法
public TreeSet():使用自然排序,当前里面存储的类型必须实现Comparable
要点:必须重写Comparable~!
例子
public class Student implements Comparable<Student>{
private String name ;
private int age ;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写
@Override
public int compareTo(Student s) { //存储到每一个学生对象
//主要排序条件:
// 需要按照学生的年龄从小到大排序!
int num = this.age - s.age ;
//int num = s.age - this.age ;
//年龄相同,比较姓名的内容是否相同
int num2 =(num==0)?(this.name.compareTo(s.name)):num ;
return num2;
}
}
public class TreeSetTest {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>() ; //无参构造方法
Student s1 = new Student("gaoyuanyuan",35) ;
Student s2 = new Student("gaoyuanyuan",35) ;
Student s3 = new Student("gaoyuanyuan",25) ;
Student s4 = new Student("wenzhang",38) ;
Student s5 = new Student("mayili",45) ;
Student s6 = new Student("yaodi",20) ;
Student s7 = new Student("baoqiang",32) ;
Student s8 = new Student("mabaoguo",65) ;
Student s9 = new Student("zhangsanfeng",65) ;
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
ts.add(s5) ;
ts.add(s6) ;
ts.add(s7) ;
ts.add(s8) ;
ts.add(s9) ;
//遍历
for(Student s:ts){
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
//自然(自动排序):
2比较器排序
比较器排序:
创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序。
在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,使用比较器排序
Map集合 <K, V>两个子实现类
将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值
Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关
Collection集合的数据结构是针对元素有效
常用功能
V put(K key,V value) 添加键值对
V remove(Object key) 删除Map的键,返回被删除键对应的值
void clear() 清空Map
boolean containsKey(Object key) 判断是否包含指定的键
boolean containsValue(Object value) 判断是否包含指定的值
boolean isEmpty() 判断map是否为空
int size() 获取map的键值对元素
遍历功能
方式1:根据键找值
获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
方式2:
根据键值对对象找键和值
获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
1:HashMap<K, V>
例子
2:TreeMap<K, V>
例子