选择排序
1、使用0角标对应的元素和后面角标对应的元素依次比较,第一次比较完,最小值出现在最小索引处
2、第二次使用1角标对应的元素和后面的元素进行比较,比较完后,第二小的值出现在第二个索引处
3、总共比较的次数:数组长度 -1
for(int x = 0 ; x < array.length-1;x++){ //外层比较次数
for(int y = x +1; y< array.length ; y ++){ //里面元素比较
//后面元素比较前面元素小,小的往前放
if(array[y] < array[x]){
int temp = array[y] ;
array[y] = array[x] ;
array[x] = temp ;
} } } }
Object类
object重点功能
1、getClass() 获取正在运行的类; 返回字节码文件对象(类的全限定名称)
Student s1 = new Student() ;
Class c1 = s1.getClass() ;
System.out.println(c1) ;//class com.qf.object_01.Student (class标记类 包名.类名-->类的全限定名称)
2、toString() 默认返回 :全类名+@+哈希值的十六进制。子类往往重写该方法,用以返回对象的字符串表示形式。
Student s1 = new Student("高圆圆",44) ;
s1.toString();
3、hashCode() 返回对象的哈希码值,不同的对象,它的哈希码值不同。 (理解为 "地址值",它不是实际意义的地址值----通过哈希算法算出来的)。
该方法往往和equals()一起被重写,用以比较自定义的类的对象属性是否相等。
4、protected Object clone() throws CloneNotSupportedException 克隆方法:创建并返回此对象的"副本"----前提是自定义的类型必须实现Cloneable接口,否则无法克隆
Student s1 = new Student() ;
Object o = s1.clone();
class Student implements Cloneable()
5、finalize() Object类的垃圾回收方法
protected void finalize()throws Throwable--跟gc垃圾回收器有关系
Cloneable接口:某个类如果能够实现这个接口,那么这个类对象就可以克隆
如果一个接口没有成员变量,连成员方法都没有,将这类接口称为"标记接口"
Object类的clone方法里面被 native:本地方法---非Java语言实现
面试题:在Java中获取一个类的字节码文件对象的方式有几种
1、public final Class getClass(): 获取正在运行的类; (返回字节码文件对象)
Class c1 = s1.getClass() ;
2、在Java中任意类型的class属性 举例: Class c = 类名.class
Class c3= Student.class ;
3、Class类提供的一个静态方法
public static Class forName(String classPathName)throws ClassNotFoundException :参数为当前类的全限定名称
Class c4 = Class.forName("com.qf.object_01.Student") ;
面试题: ==和equals的区别
1、 ==连接的是两个基本数据类型:比较的是数据值是否相等
==连接的是引用类型,比较的是引用类型的地址值是否相等
2、 equals: Object的 equaels()方法默认比较的是两个对象的地址值相同。
如果要比较成员信息的内容是否相同,必须重写Object的equals方法以及hashCode(),重写之后比较的是内容是否相同
equals重写之后,是比较里面的每一个成员信息是否一样,如果都一样。还有比较两个成员对应的hashCode()是否一样,如果一样,是同一个人
看程序,写结结果
考点:
==和equals的区别:
==:连接的是两个引用类型的数据,比较的是两个对象的地址是否相同
Object的equals():默认比较的是两个对象的地址值是否相同,子类重写了equals(),就比较两个对象的内容是否相同
字符串常量相加:先相加,然后看结果,是否在常量池中,如果有,直接返回值地址;否则开空间
字符变量相加:先在常量池开辟空间,然后在操作;
public class StringDemo3 {
public static void main(String[] args) {
String s1 = "hello" ;
String s2 = "world" ;
String s3 = "helloworld" ;
System.out.println((s1+s2)==s3) ;
System.out.println((s1+s2).equals(s3)) ;//String类重写了Object的equals方法,只管字符串内容是否一样
System.out.println("----------------------------") ;
System.out.println(("hello"+"world")==s3) ;//常量先相加,然后常量池中找,存在返回地址;否则常量池开空间
System.out.println(("hello"+"world").equals(s3)) ;//比较内容是否相同
}
}
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对象;
创建键盘录入对象
Scanner sc = new Scanner(in) ;
提示并录入数据
System.out.println("请您输入一个数据:");
//现在录入一个int
//int a = sc.nextInt() ;//java.util.InputMismatchException:输入类型不匹配 :接收结果类型和录入的类型不匹配
//boolean hasNextXXX方法():判断下一个录入的是为XXX类型
if(sc.hasNextInt()){//如果下一个录入的是int类型
int a = sc.nextInt() ;
System.out.println(a);
}else if(sc.hasNextLine()){ //录入的下一个是String类型
String s = sc.nextLine() ;
System.out.println(s);
}else{
System.out.println("没有这个类型");
}
String类
String类:代表字符串,是一个常量,创建之后,其值不能更改。字符串的底层就是一个字符数组组成!char[]—>String。 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
1、public String():创建字符串对象
String s = new String() ;
System.out.println("s:"+s) ;//打印不是地址,而空字符串,String类重写了Object类的toString()
2、 public String(String original):将指定的字符串传进去,构造一个字符串对象
String s2 = new String("hello") ;
3、public String(char[] value):将字符串数组---构造成String
char[] chs = {'高','圆','圆'} ;
String s3 = new String(chs) ;
4、public String(char[] value,int offset,int count):将一部分字符数组转换成String
String s4 = new String(chs,1,2) ;
System.out.println("s4:"+s4);
5、public String(byte[] bytes)将字节数组---构造成String :
byte[] bytes = {97,98,99,100,101} ;
String s5 = new String(bytes) ;//转换过程,将每一个数据找ASII码表对应的字符值,构造成字符串
System.out.println("s5:"+s5) ;//abcde
6、public String(byte[] bytes, int offset,int length)
String s6 = new String(bytes,2,3) ;
面试题: 创建两种字符串的方式的区别
String s1 = “hello” ;
String s2 = new String(“hello”) ;
第一个格式:创建一个对象,直接在常量池中创建;
第二个格式:需要在堆内存开辟空间,而且指向常量池地址:内存创建了两个对象
两个都是创建字符串实例,但是推荐第一种,从内存角度考虑,消耗内存资源不严重
String类中常用的获取功能
String类中常用的获取功能:
String s = "helloworld" ;
1)public char charAt(int index) 获取指定索引值对应的字符
char ch = s.charAt(0) ;
2)public int length() :字符串特有功能:获取字符串长度
s.length()
3)public String concat(String str):拼接功能 将指定的字符串拼接到该字符串末尾,获取新的字符串
String str = s.concat("高圆圆");
4)public int indexOf(String str)返回指定字符串第一次出现索引值
System.out.println(s.indexOf("o"));
public int lastIndexOf(String str):返回指定子字符串最后一次出现的索引值
System.out.println(s.lastIndexOf("o"));
5)public String[] split(String regex):字符串拆分功能
String s2 = "Java-Python-C-Golang-R-Hadoop" ;
String[] strArray = s2.split("-"); //字符串数组
6)截取功能
public String substring(int beginIndex,int endIndex)
从指定位置开始,截取到endIndex-1处结束,包前不包后
String ss = s.substring(5, 8);
public String substring(int beginIndex) 从指定位置开始默认截取到末尾
String ss = s.substring(5));
String类的常用的转换功能
String类的常用的转换功能
String s = "中国" ;
1、 public byte[] getBytes(): 将字符串转换成字节数组 (编码:将能看懂的东西--->变成看不懂的) (使用平台默认字符集)idea设置的平台字符集:utf-8:一个中文三个字节
byte[] bytes = s.getBytes() ;
2、public char[] toCharArray() :将字符串转换成字符数组 (使用居多)
char[] chars = s.toCharArray();
3、public static String valueOf(常见的基本类型int/long/double/float/boolean/Object):
String的万能方法:将上面的常用类型--转换成String
int i = 100 ;
String result = String.valueOf(i);
4、 public String toUpperCase():将指定字符串转换成大写
s.toLowerCase()
5、 public String toLowerCase():将指定字符串转换成小写
s.toUpperCase()
String类判断功能以及其他功能
String类判断功能以及其他功能:
String s = "helloworldJavaEE" ;
1、public boolean constains(String str):判断大串中是否包指定的子字符串
System.out.println(s.contains("owo"));
2、public boolean equals(Object anObject)):比较两个字符串内容是否相同。区分大小写
System.out.println(s.equals("HelloworldJavaEE"));
3、public boolean equalsIgnoreCase(String anotherString)):忽略大小写比较
System.out.println(s.equalsIgnoreCase("HelloworldJavaEE"));
4、public boolean startsWith(String prefix):字符串是否以指定的前缀开头
System.out.println(s.startsWith("hel"));
5、public boolean endsWith(String str):字符串是否以指定的后缀结尾
System.out.println(s.endsWith("EE"));
其他功能:
6、public String replace(char oldChar,char newChar)替换功能:使用指定的新的字符替换以前的字符
System.out.println(s.replace('l','*'));
7、public String trim():删除前后两端空格
应用场景:trim(): 使用io(intput输入 Output输出)流进行 读写复制(文件内容在网络中传输)
件内容前后有一些空字符出现,获取到文件内容之后,先去trim()去除两端空格
String s1 = " hello ";
String s2 = s1.trim() ;
面试题:字符串按照字典顺序比较结果是怎么计算的
面试题:
String s1 = "hello" ;
String s2 = "hel" ;
s1.compareTo(s2)
这个两个字符串按照字典顺序比较结果是怎么计算的?
两个字符串--->底层是以字符数组存储-获取字符数组长度,获取长度的最小值
使用最小值作为 while循环条件, 如果没有取到最小值,一直循环
循环逻辑:
通过获取两个字符数组的每一个字符,如果都相同,最终临界条件达到 ,两个字符数组长度相减
如果获取到字符,如果两个字符不相等,直接是两个字符---对应的ASCII码表的值相减---直接得到字典顺序的值
compareTo源码
final class String{
private final char value[]; //字符数组
public int compareTo(String anotherString) {//s1.compareTo(s2)
int len1 = value.length; //int len1 = 获取s1字符数组.length= 5
int len2 = anotherString.value.length; //int len2 = 获取s2字符数组.length=3
int lim = Math.min(len1, len2); //int lim = Math.min(len1,len2) ; //获取最小值 =3
char v1[] = value; //char v1[] = {'h','e','l','l','o'} ;
char v2[] = anotherString.value; //char v2[] = {'h','e','l'} ; //char v2[] = {'a','b','c'} ;
int k = 0; //统计变量k = 0
while (k < lim) { //while(k < lim) 0<3 1<3 2<3 3<3
char c1 = v1[k]; //char c1 = v1[0] = 'h' ; //char c1 = v1[1] = 'e'; //char c1 = v1[2]='l';
char c2 = v2[k]; //char c2 = v2[0] ='h' ; //char c2 = v2[1] = 'e' ;//char c2 = v2[2] ='l';
//char c2 = v2[0] = 'a' ;
if (c1 != c2) { //如果两个字符不相等
return c1 - c2; //直接两个字符相减 --- 'h' - 'a' = 104- 97 = 7
}
k++; //k++-->1--->2--->3
}
return len1 - len2; //len1-len2 ---->5-3 = 2
}
}
String的equals方法源码
String s1 = new String("hello") ;
String s2 = "hello" ;
s1.equals(s2) ;
class String{
private final char value[]; //value属性:是个字符数组
public boolean equals(Object anObject) { //
if (this == anObject) { //s1和s2地址值不一样
return true;
}
if (anObject instanceof String) { // if(s2 instanceOf String):s2这个变量是否为String的实例
String anotherString = (String)anObject; //向下转型---String类型
int n = value.length; //s1= {'h','e','l','l','o'} ; --获取字符数组长度5
if (n == anotherString.value.length) { //if(5 == 5) //s2-=={'h','e','l','l','o'}
char v1[] = value; //v1-->s1的底层字符数组
char v2[] = anotherString.value; //v2-->s2的底层字符数组
int i = 0; //统计变量 i = 0
while (n-- != 0) {
//i=0
if (v1[i] != v2[i]) { //if(v1[0] != v2[0]) 'h' 'h'
return false;
}
i++; i++ -->1 --->
}
return true; 已经取到最大索引值 ,两个字符串中字符串的字符都一样
return true;
}
}
return false;
}
}
面试题:数组中、String类在集合中有没有length()
数组中length属性,获取数组长度
String类中有length(),获取字符串长度
集合中没有。size():获取集合中元素数
String方法练习1
需求:
键盘录入一个字符串,将字符串的第一个字符转换成小写,其余字符转换成大写(不考虑特殊字符)
public class StringTest {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入字符串
System.out.println("请输入一个字符串:") ;
String line = sc.nextLine() ;
1)先将line的第一个字符截取出来
String s1 = line.substring(0,1) ;
2)将s1--->转换成大写
String s2 = s1.toUpperCase() ;
3)将line字符串 从第二个字符开始截取出来
String s3 = line.substring(1) ;
4)将s3-->转换成小写
String s4 = s3.toLowerCase() ;
5)将s2和s4拼接---String的concat拼接功能
String result = s2.concat(s4)
一步走 :链式编程
String result = line.substring(0,1).toUpperCase().concat(line.substring(1).toLowerCase()) ;
String方法练习2
需求:
已知数组静态初始化的
int[] arr = {24,57,69,13,98} ;
定义功能,将数组转换成String --->把数组遍历出来--->每一个元素拼接成String
public class StringTest2 {
public static void main(String[] args) {
//已知数组
int[] arr = {24,57,69,13,98} ;
//调用将数组转换String的方法
String result = arrayToString(arr) ;
System.out.println(result) ;
}
//将转换成String
public static String arrayToString(int[] array){
//定义一个最终结果变量
String s = "" ;
s += "[" ;//或者使用字符串的concat功能
//遍历数组
for(int x = 0 ; x < array.length ; x++){
if(x==array.length-1){
//最后一个元素
s+=array[x] +"]" ;
}else{
//中间元素
s+= array[x] +", ";
}
}
return s ;
}
}
StringBuffer
StringBuffer:字符串缓冲区,线程安全的,支持可变的字符序列
构造方法
1、 public StringBuffer():无参构造方法,里面空的字符序列,初始容量16个字符(默认容量足够大)
StringBuffer sb = new StringBuffer() ;
2、 public StringBuffer(String str):将字符串构造为StringBuffer类型,容量是大小:当前的里面的字符串长度+16
StringBuffer sb2 = new StringBuffer("hello") ;
3、 public StringBuffer(int capacity):创建一个字符串缓冲区,指定容量大小
StringBuffer sb3 = new StringBuffer(50) ;
StringBuffer的添加/删除的功能
StringBuffer的添加/删除的功能
StringBuffer sb = new StringBuffer() ;
1、添加: public StringBuffer append(任意java类型) 可以将任意类型的元素添加(在末尾追加)到字符串缓冲区中,返回值是字符串缓冲区本身
StringBuffer sb3 = sb2.append("helloworld"); //sb.append("hello").append('A').append(true).append(100).append(new Object());
2、插入: public StringBuffer insert(int offset,任意java类型):在指定位置处的序列前面插入新的序列
sb.insert(5,"高圆圆") ;
3、删除: public StringBuffer deleteCharAt(int index):在指定位置处删除指定的字符,返回字符串缓冲区本身
sb.deleteCharAt(5) ;
4、删除: public StringBuffer delete(int start,int end):从指定位置start处开始到end-1处的字符序列删除, 返回值字符串缓冲区本身
sb.delete(5,10) ;
StringBuffer其他功能
StringBuffer其他功能:
替换功能
StringBuffer sb = new StringBuffer() ;
sb.append("hello") ;
sb.append("world") ;
sb.append("javaee") ;
1、public StringBuffer replace(int start,int end,String str)
使用指定的字符串str从指定位置开始到end-1处进行替换,返回该字符串缓冲区本身
sb.replace(5,10,"高圆圆") ;
2、 public String substring(int start):从指定位置开始截取,默认截取到末尾,返回被截取后的字符串
String str = sb.substring(5);
3、public String substring(int start,int end):从指定位置开始截取到指定位置end-1处,返回被截取后的字符串String
String str = sb.substring(5,8);
获取字符串缓冲区的长度 ---int length()
获取字符串缓冲区的容量---int capacity()
StringBuffer的特有功能:反转
StringBuffer的特有功能:
public StringBuffer reverse() :字符串缓冲区反转功能,将字符串缓冲区中所有的字符序列反转!
需求:
键盘录入一个字符串,将字符串反转
方式1:
1)将录入的字符串---->转换成字符数组
2)定义一个String s = "" ;
3)将字符数组倒着遍历
for(int i = 字符数组.length-1;i>0 ;i --){
s += 字符数组[i] ;
}
4)返回结果变量s
public class StringBufferDemo3 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请输入一个字符串:" ) ;
String line = sc.nextLine() ;
//调用一个功能完成
String result = reverse(line);
System.out.println(result) ;
}
//方式2:使用StringBuffer的反转功能
public static String reverse2(String s){
StringBuffer sb = new StringBuffer() ;
sb.append(s) ;
return sb.reverse().toString() ;
//return new StringBuffer(s).reverse().toString() ;
}
public static String reverse(String s){
//定义一个空字符串
String result = "" ;
//将s字符串-->转换功能 --->字符数组
char[] chs = s.toCharArray();
for(int x = chs.length-1 ; x >= 0 ; x--){
result += chs[x] ;
}
return result ;
}
}
反转应用案例:"To be or not to be" 反转为oT eb ro ton ot eb
public class Test3 {
public static void main(String[] args) {
String s = "To be or not to be" ;
String result = reverseMyStr(s);
}
private static String reverseMyStr(String s) {
//根据空格分割字符串
String[] strArray = s.split(" ") ;
//创建一个字符串缓冲区
StringBuffer sb =new StringBuffer() ;
StringBuffer buffer = null ;
//遍历字符串数组
for(int x = 0 ; x <strArray.length;x++ ){
String ss = strArray[x] ;
//创建一个新的字符串缓冲区区
buffer = new StringBuffer(ss) ; // Tobeornottobe
//反转
buffer.reverse() ;//otebrotonoteb
buffer.append(" ") ;
sb.append(buffer) ; //
}
return sb.toString() ;
}
}
StringBuffer和String的相互转换
一、String---->StringBuffer
String s = "hello" ;
StringBuffer sb = s ;
方式1)可以通过StringBuffer的有参构造方法
//创建一个字符串缓冲
StringBuffer sb = new StringBuffer(s) ;
方式2:通过StringBuffer的无参构造方法+append(String str)
StringBuffer sb2 = new StringBuffer() ;
sb2.append(s) ;
二、StringBuffer-->String
//有一个字符串缓冲区--->里面存在字符序列
StringBuffer buffer = new StringBuffer("100") ;
方式1) -->public String toString()
String str = buffer.toString();
方式2)String类的构造方法
String str2 = new String(buffer) ;
相互转换练习
判断该字符串是否是对称字符串
方式一:
public static boolean isSame2(String s){
//利用StringBuffer的反转
//如果将s--->转换StringBuffer---->反转----->转换成String---->和转换之前String可以equals(),就是对称的,否则不对称
return new StringBuffer(s).reverse().toString().equals(s) ;
}
方式二:
public static boolean isSame(String s){
boolean flag = true ;
//将字符串转换字符数组
char[] chs = s.toCharArray();
for(int x = 0 ; x < chs.length/2 ; x++){
if(chs[x] !=chs[chs.length-1-x]){//两个字符比较 :比较ASCII码表的值是否相同
flag = false ;
break ;
}
}
return flag ;
}
}
StringBuffer和StringBuilder的区别
StringBuffer和StringBuilder的区别
共同点:
他们都支持可变的字符序列,都代表字符串缓冲区(存储的都是字符序列)(都是容器),底层都是会存在char[];
他们作为方法形式参数,形式参数的改变都会影响实际参数
他们具有相互兼容的API
不同点:
StringBuffer是线程安全的类,执行效率低。他们几乎所有的成员方法都有一个关键字"synchronized"-->同步锁(悲观锁),能够解决线程安全问题
StringBuilder是线程不安全的类,单线程程序(不考虑安全,只考虑执行效率)使用StringBuilder去替代StringBuffer,提高执行效率(相对StringBuffer,执行效率高)
String和int的相互转换
int--->String
1)使用字符串拼接符号 ""+任何类型数据= "新的字符串"
2)int--->Integer---->String
int i = 100 ;
Integer integer = new Integer(i) ;
String str = integer.toString() ;
3)Integer的静态方法 public static String toString(int i)
String str2 = Integer.toString(i) ;
String--->int
1)String---->Integer---->int
String source = "10" ;
Integer integer2 = new Integer(source) ;
int value = integer2.intValue() ;
2)Integer提供的静态方法 public static int parseInt(String s)
int value2 = Integer.parseInt(source);
面试题:StringBuffer和StringBuilder的区别?
1、这两个类都是字符串缓冲区,都支持可变的字符序列,(都有相同的功能)
2、StringBuffer:使用在多线程环境里面,能够保证线程安全---意味着同步---执行效率低
3、StringBuilder:是StringBuffer的简易替换,用于在单线程环境中,线程不安全---不同步---执行效率高
4、单线程使用StringBuilder:效率高(速度快)
基本数据类型对应的引用类型
jdk提供了一个类Integer类,提供了一些功能:十进制转换成对应的进制的方法(静态方法)
四类八种的基本数据类型都会自动提升 对应的引用类型 jdk5以后新特性:自动拆装箱
拆箱:这些包装类类型--->降为 基本类型
装箱: 就是基本类型--->提升 对应的引用类型
基本类型 引用类型的默认值null
byte Byte
short Short
int Integer(特殊)
long Long
float Float
double Double
char Character(特殊)
boolean Boolean
这些四类八种中的基本数据类型可以String进行相互转换的---->中间桥梁 ---->对应的基本类型的包装类类型
//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));
//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) ;
Integer
Integer类表示包含int类型的值
Integer类的构造方法:
1、public Integer(int value):创建一个Integer实例,里面包含的int类型的值
2、public Integer(String s) throws NumberFormatException: 将数字字符串转换成Integer的实例
可能会出现数字格式化异常(字符串如果不是数字字符串,就会出现这个异常)
//创建一个Integer实例
//public Integer(int value):创建一个Integer实例,里面包含的int类型的值
int a = 100 ;
Integer i = new Integer(a) ;
System.out.println(i) ;
// public Integer(String s) throws NumberFormatException:
//Integer i2 = new Integer("hello") ;//NumberFormatException:数字格式化异常
Integer i2 = new Integer("50") ;
System.out.println(i2);
Integer的自动拆装箱
//将100赋值给Integer类型的变量i
Integer i = 100 ; //整数常量赋值Integer类型变量i 装箱
i += 200 ; //先拆箱,在装箱
Integer i = Integer.valueOf(100); //自动装箱 int--->Integer //public static Integer valueOf(int i)
i = Integer.valueOf(i.intValue() + 200); // i.intValue()--->public int intValue()--->将Integer-->int //先自动拆箱,然后再通过valueOf(300)--->再装箱
int基本类型和引用String的相互转换
int基本类型和引用String的相互转换 (重点)
String---int: int 变量名 = Integer.parseInt(已知的数字字符串) 推荐
int---->String: Integer类提供静态方法 String 变量名 = Integer.toString(int类型的值)
int---->String
方式1:使用拼接符号
int i = 100 ;
String s = "" ;
s += i ; //拼接符号 s = s+i
System.out.println(s) ;//"100"
方式2:int---->Integer----->String
//int-->Integer
Integer integer = Integer.valueOf(i);
//Integer--->String
String str = integer.toString();
方式3:Integer---->String
//public static String toString(int i)
String str2 = Integer.toString(i);
String---->Integer---->int
一:一步执行
//Integer类提供了静态方法
//public static int parseInt(String s)throws NumberFormatException:要转的字符串必须为数字字符串
//万能方法:String--->long --->Long引用提供静态方法 public static long pasreLong(String str)
String source = "1990" ;
int value = Integer.parseInt(source);
二:分步执行: //Integer(String str)
Integer ii = new Integer(source) ;
//Integer--->int
int value2 = ii.intValue();
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
return new Integer(i); //如果上if不成立,重新开辟新的空间创建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) ; 不在-128~127范围, 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 。Integer重写了equals方法
Character
char类型的包装类类型:Character
构造方法:
//public Character(char value):包含char类型的值
Character ch = new Character((char)97) ;
成员方法:
判断功能:
1、 public static boolean isDigit(char ch):判断当前这个字符是否为数字
Character.isDigit('A')
2、 public static boolean isLowerCase(char ch):判断当前这个字符是否小写
Character.isLowerCase('a')
3、 public static boolean isUpperCase(char ch):判断当前这个字符是否大写
Character.isUpperCase('a')
BigDecimal类
BigDecimal这个类是对小数可以进行精确计算的
构造方法:
public BigDecimal(String val):将String类型数据构造成BigDecimal
将double数据---使用"小数字符串"
成员方法:
1、 public BigDecimal add(BigDecimal augend):求和
BigDecimal bd1 = new BigDecimal("0.35") ;
BigDecimal bd2 = new BigDecimal("0.35") ;
System.out.println(bd1.add(bd2)) ;
2、public BigDecimal subtract(BigDecimal subtrahend):相减
BigDecimal bd3 = new BigDecimal("1.01") ;
BigDecimal bd4 = new BigDecimal("0.036") ;
System.out.println(bd3.subtract(bd4));
3、public BigDecimal multiply(BigDecimal multiplicand):乘法
BigDecimal bd5 = new BigDecimal("0.35") ;
BigDecimal bd6 = new BigDecimal("2.01") ;
System.out.println(bd5.multiply(bd6));
4.1、public BigDecimal divide(BigDecimal divisor,int roundingMode):除法,第二个参数为舍入模式
bd3.divide(bd4,BigDecimal.ROUND_HALF_UP);
4.2、public BigDecimal divide(BigDecimal divisor,
int scale,//保留几位小数
int roundingMode) //舍入模式
bd3.divide(bd4,1,BigDecimal.ROUND_HALF_UP);
BigDecimal提供的模式 public static final int ROUND_HALF_UP:四舍五入
Random
Random:伪随机数生成器,可以产生随机数
两个构造方法:
public Random() :无参构造方法(推荐)
public Random(long seed):有参构造,创建一个指定long类型的变量的随机数生成器
两个成员方法:
public int nextInt(): 产生伪随机数在,取值是int类型的范围内
public int nextInt(int n):产生0-n之间的随机数(推荐)
public class RandomDemo {
public static void main(String[] args) {
Random r = new Random(1000) ;
Random r = new Random() ;
//产生10个随机数
for(int x = 0 ; x < 10 ; x ++){
int number = r.nextInt(); //产生是int类型的范围内随机数
int number = r.nextInt(50); //产生0-50范围内随机数
}
}
}
System类
java.lang.System:不能实例化:提供了静态字段(静态变量)
1、public static final PrintStream out :标准 打印输出流
PrintStream ps = System.out ;
ps.print(100) ;
2、public static final PrintStream err 标准错误输出流
PrintStream ps2 = System.err ;
ps2.println("这是一个错误输出流打印数据,提示错误信息");
3、 public static final InputStream in 标准输入流
InputStream is = System.in ;
Scanner sc = new Scanner(is) ;
System类常用的成员方法:
1、public static long currentTimeMillis() 计算当前系统时间毫秒值 (很少单独用)
用来计算当前某个程序的时间复杂度(运行效率)
long start = System.currentTimeMillis() ;
long end = System.currentTimeMillis() ;
System.out.println("共耗时:"+(end-start)+"毫秒");
2、public static void gc() 收到开启垃圾回收器 ---会调用finalize(),回收没有更多引用的对象
System.gc();
3、 public static void exit(int status):
System.exit(0) ;//参数为0,正常终止jvm
4、public static void arraycopy( //数组拷贝
Object src, //原对象
int srcPos, //原对象中的某个位置
Object dest, //目标对象
int destPos, //目标对象的某个位置
int length) //指定的长度
)
int[] arr = {11,22,33,44,55} ;
int[] arr2 = {1,2,3,4,5,6,7,8} ;
System.arraycopy(arr,1,arr2,2,3);
Date类
java.util.Date:表单特定的日期时间,还允许格式化和解析日期字符串
构造方法:
1、public Date():创建当前日期对象:获取当前系统日期时间
Date date = new Date() ;
System.out.println(date) //格式:Thu Mar 16 14:07:46 CST 2023
2、public Date(long date):里面传入long类型的时间毫秒值,获取的表示从标准基准时间(称为“时代”)即1970年1月1日00:00:00 GMT起的指定毫秒数
long time = 1000 ;
Date date = new Date(time) ; //毫秒
成员方法:
1、 public long getTime():将Date对象转换成long类型时间毫秒值
2、public void setTime(long time):设置日期时间,参数时间毫秒值
Date和String日期文本相互转换
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
案例:
public class DateDemo2 {
public static void main(String[] args) throws ParseException {
//当前系统日期对象
Date date = new Date() ;
Date---->格式化---->String日期文本
//1)public SimpleDateFormat(String pattern):参数是日期文本模式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss") ;
//2)格式化:public final String format(Date date)
String dataStr = sdf.format(date);
System.out.println(dataStr) ;
String日期文本--->格式化---->Date
String source = "2008-5-12" ;
//创建SimpleDataFormat
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd") ;
//解析public Date parse(String source)throws ParseException
//当SimpletDateFormat和给定日期文本格式不一致,就解析出错
Date date2 = sdf2.parse(source);
System.out.println(date2);
}
}
相互转换练习案例
键盘录入出生年月日,计算来到这个世界多少天了?
1)键盘录入String dateStr = "1990-02-27"
2)将dateStr日期字符串---->java.util.Date
3)获取当前那个Date日期时间 毫秒值 long getTime()
4)System提供了一个方法获取当前系统时间毫秒值
5)时间差值---然后换算成天
public class DateTest {
public static void main(String[] args) throws ParseException {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请输入您的出生年月日:" ) ;
String dateStr = sc.nextLine() ;//yyyy年MM月dd日/yyyy-MM-dd
//将dateStr---->java.util.Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;
Date date = sdf.parse(dateStr);
//获取当前date所在时间毫秒值
long oldTime = date.getTime();
//获取当前系统时间毫秒值
long nowTime = System.currentTimeMillis() ;
long time = nowTime - oldTime ;
System.out.println("您来到这个时间有:"+(time/1000/60/60/24)+"天");
}
}
Calendar类
java.util.Calendar:日历类(抽象类)
提供了获取年,年中的月,月中的日期,小时,小时分钟数,分钟中的秒数都可以获取到
如果有一个类是抽象类,可以直接new子类,或者是它提供了一些静态方法---->完成了一些事情,创建子类对象,返回值是当前抽象类的本身
成员方法:
1、public static Calendar getInstance() 创建日历对象
2、public int get(int field):通过日历对象获取日历中的字段值
参数:Calendar中提供的一些静态字段
1、 public static final int YEAR:年份
2、public static final int DAY_OF_MONTH/public static final int DATE:月中的日期
3、 public static final int MONTH:月份
4、 public abstract void add(int field,int amount):给指定的日历字段值添加或者减去时间偏移量
public class CalendarDemo {
public static void main(String[] args) {
//创建一个日历对象
//Calendar c = new Calendar() ; //不能实例化:抽象类
Calendar c = Calendar.getInstance(); //getInstance()--->创建Calendar类的子类对象
//public int get(int field):通过日历对象获取日历中的字段值
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) ;//默认计算0-11
int date = c.get(Calendar.DAY_OF_MONTH) ;
System.out.println(year+"-"+(month+1)+"-"+date);
//public abstract void add(int field,int amount):给指定的日历字段值添加或者减去时间偏移量
//3年后的今天
c.add(Calendar.YEAR,3) ;
year = c.get(Calendar.YEAR) ;
month = c.get(Calendar.MONTH) ;//默认计算0-11
date = c.get(Calendar.DAY_OF_MONTH) ;
System.out.println(year+"-"+(month+1)+"-"+date);*/
//5年前的10天前
c.add(Calendar.YEAR,-5);
c.add(Calendar.DAY_OF_MONTH,-10);
year = c.get(Calendar.YEAR) ;
month = c.get(Calendar.MONTH) ;//默认计算0-11
date = c.get(Calendar.DAY_OF_MONTH) ;
System.out.println(year+"-"+(month+1)+"-"+date) ;
}
}
集合和数组的区别
集合和数组区别?
1)长度区别
数组:固定
集合:可变
2)存储数据类型的区别?
数组:可以存储基本数据类型,也可以存储引用数据类型
集合:只能存储引用类型 集合<泛型>
3)存储元素的区别?
数组:数组存储的元素的数据类型必须一致
集合:如果没有明确<泛型>,可以存储任意的引用类型(包含Object)
Collection
集合框架体系结构图:
Collection基本功能:
Collection:单例集合顶层次的根接口,不能new,没有直接子实现类,是通过它子接口的子实现类来实例化
泛型: 集合里面创建的时候,如果不带泛型可能程序安全问题;带了<>,模拟创建数组的时候,明确了数据类型
<E>:element
<T>:Type
<K>:Key键
<V>:Value值
Collection基本功能:
添加元素:
boolean add(E e):添加元素
删除:
boolean remove(Object o):删除指定的元素
void clear():暴力删除:清空集合
判断:
boolean contains(Object o):是否包含指定的元素
boolean isEmpty():判断集合是否为空
Collection<String> c = new ArrayList<>() ;
c.add("hello") ;//添加元素
c.remove("hello")//删除元素
c.clear();//清空集合
boolean b = c.isEmpty();//判断集合是否为空
c.contains("hello") //是否包含指定的元素,底层依赖Object 的equals方法,默认比较的地址值是否相等
普通for遍历集合
Collection集合高级功能:
Object[] toArray():集合的传统方式遍历 将集合转换成对象数组
//创建一个集合Collection
Collection<Student> c = new ArrayList<>() ;
//创建5个学生
Student s1 = new Student("文章",35) ;
Student s2 = new Student("王宝强",37) ;
Student s3 = new Student("高圆圆",44) ;
Student s4 = new Student("赵又廷",46) ;
Student s5 = new Student("马伊琍",40) ;
Student s6 = new Student("马伊琍",40) ;
//添加功能
c.add(s1) ;
c.add(s2) ;
c.add(s3) ;
c.add(s4) ;
c.add(s5) ;
c.add(s6) ;
//Object[] toArray()
Object[] objects = c.toArray(); //objects--->存储5个学生
for(int x = 0 ;x < objects.length ; x++){
//System.out.println(objects[x]);// objects[x] 类型Object--->每一个学生对象 new Student()
//向下转型
Student student = (Student) objects[x];
System.out.println("学生的姓名是:"+student.getName()+",年龄是:"+student.getAge());
Iterator迭代器遍历集合
Iterator<E> iterator():Collection专有迭代器(遍历集合) (过渡)
Iterator迭代器接口:
方法:
1、boolean hasNext(): 判断迭代器里面是否下一个可以遍历的元素
2、 E next():获取迭代器的下一个元素 (和迭代器中的类型一致)
开发中---集合遍历---->都用jdk5以后新特性:增强for循环 代替上面迭代器
//使用Collection存储String字符串并进行遍历---使用Collection迭代器
Collection<String> c = new ArrayList<>() ;
//添加String
c.add("android") ;
c.add("JavaEE") ;
c.add("mysql") ;
c.add("hadoop") ;
//获取Collection的迭代器
//Iterator<E> iterator()
Iterator<String> it = c.iterator();
//E next() //E---类型需要和泛型的类型一致的
//while循环 遍历
while(it.hasNext()){
String s = it.next();
System.out.println(s+"---"+s.length());
迭代器实现原理:就是ArrayList集合的内部类实现Itr间接实现了两个功能
interface Iterator<E>{
boolean hasNext() ;判断是否有下一个可以迭代的元素
E next() ;获取下一个元素
}
interface Iterable<T>{
Iterator<E> iterator();
}
interface Collection<E> extends Iterable {
Iterator<E> iterator();
}
interface List<E> extends Collection<E>{
Iterator<E> iterator();
}
//具体的子实现类
public class ArrayList<E> implements List<E>{
public Iterator<E> iterator() {
return new Itr();
}
//私有的成员内部类Itr
private class Itr implements Iterator<E> {
boolean hasNext(){
}
Object next(){
...
}
}
}
增强for遍历集合
格式:
for(集合中存储的数据类型 变量名 : 集合对象){ //相当于迭代器,同样不能并发修改集合
使用这个变量名即可;
}
注意:要使用增强for遍历集合,集合对象不能null;
防止空指针异常,在使用增强for之前,对集合进行非空判断
使用案例:
Collection<String> c = new ArrayList<>() ;
c.add("hello") ;
c.add("world") ;
c.add("JavaEE") ;
c.add("mysql") ;
for(String s:c){//增强for替代迭代器
System.out.println(s);
}
并发修改异常
ConcurrentModificationException:并发修改异常
什么叫并发:在某个时间点上同时进行
在集合这块出现ConcurrentModificationException原因:
当使用迭代器去遍历元素的时候,同时不能使用集合对象去操作(修改或添加...)元素,就会出现这个异常。因为,迭代器在遍历元素的时候,集合添加一个新的元素,迭代器不知道
解决方案:
1)集合遍历,集合添加
2)迭代器遍历,迭代器遍历
Collection没有直接操作----->子接口List特有功能(ListIterator:列表迭代器/List集合普通for+size()+get(int index))
集合元素去重
Collection集合元素去重
新建空集合思想
去遍历以前的集合,获取所有的元素。在新集合中判断,是否包含这个以前的元素,如果不包含,把这个元素添加新集合中
使用Collection<String>,使用ArrayList具体的子类,添加重复的String类型数据,保证元素唯一
public class Test2 {
public static void main(String[] args) {
//创建Collection
Collection<String> c = new ArrayList<>() ;
c.add("hello") ;
c.add("hello") ;
c.add("world") ;
c.add("javaee") ;
c.add("world") ;
c.add("javaee") ;
//新建一个空集合思想
Collection<String> newColl = new ArrayList<>() ;
//然后:去遍历以前的集合,获取所有的元素
//在新集合中判断,是否包含这个以前的元素,如果不包含,把这个元素添加新集合中!
for(String s :c){
if(!newColl.contains(s)){//不包含。判断集合中是否包含此元素
//ArrayList里面的contains底层依赖Object的equals方法,由于现在存String类型
// String类型重写了Object的equals比较的是两个字符串内容是否相同,相同只存储一个
//自定义子类使用contains()方法时,需重写equals和hashCode方法
newColl.add(s) ;
}
}
List集合常用三个子实现类
List集合常用三个子实现类特点:
实际需求:单线程中,使用List完成一些事情,没有明确规定具体使用哪个实现类;默认使用ArrayList集合
1、默认:ArrayList
底层数据结构是数组-->查询快,增删慢! (数组,通过整数索引查询)
元素查找: 顺序查找,二分搜索(折半查找),哈希查找
线程角度:
线程不安全的类,是一个不同步,执行效率高
底层扩容机制1.5倍
2、Vector
底层数据结构是数组-->查询快,增删慢
线程角度:
线程安全的类,是同步的,执行效率低! 多线程环境下使用居多,单线程使用ArrayList代替Vector
3、LinkedList
底层数据是链表, 查询慢,增删快
线程角度:
线程不安全的类,不同步的,执行效率高
List集合特点
List集合特点:
元素有序(存储和取出一致),而且元素可以重复
Set集合:
元素唯一的,无序(存储和取出不一致)
List集合是Collection集合的子接口,它集合遍历方式:
1)Collection的Object[] toArray()
2)Collection的Iterator iterator() ;
3)使用size()+ 存储的数据类型 get(int index)通过角标获取元素内容 :普通for循环格式
4)ListIterator<E> listIterator()List集合的专有遍历方式 :列表迭代器
5)增强for循环
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);
}
//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);
}
//列表迭代器提供了一些功能,进行逆序遍历(前提必须有上面的正向遍历)
//boolean hasPrevious():判断是有上一个元素
//E previous():获取上一个元素
while(lit.hasPrevious()){
String previous = lit.previous();
System.out.println(previous);
}
//增强for (推荐)
for(String s:list){
System.out.println(s) ;
}
}
List元素去重思想
使用List集合解决并发修改异常
使用List集合解决并发修改异常
List有特有方式:
size()获取集合长度 结合 Object get(int index)通过索引值获取对应的内容
特有添加元素的方式:
void add(int index,E element):在指定位置处,添加指定的元素
List继承Collection--->Iterator是Collection的专有迭代器,没有提供添加功能,而
List集合专有遍历方式ListIterator:列表迭代器
public class ListDemo {
public static void main(String[] args) {
//使用List集合存储String
List<String> list = new ArrayList<>() ;
list.add("hello") ;
list.add("world") ;
list.add("javaee") ;
// 1)集合遍历,集合添加
//size()获取集合长度 结合 Object get(int index)通过索引值获取对应的内容
/* for(int x = 0 ; x < list.size() ; x++){
String s = list.get(x);
//判断
if("world".equals(s)){
list.add("go") ; //add()方法继承自 Collection的方法
}
}*/
//2)迭代器遍历元素,迭代器添加元素
// ListIterator<E> listIterator()
//ListIteratr--->void add(E e)将指定的元素插入列表
ListIterator<String> lit = list.listIterator(); //ListItr extends Itr :都是ArrayList的内容类
while(lit.hasNext()){
//获取下一个元素
String s = lit.next();
//判断:如果s是"world",添加一个新的"go"
if("world".equals(s)){
lit.add("go") ;
}
}
ArrayList
Arrays的toString的原码
public static String toString(int[] a) { //实际参数 --->传入数组对象
if (a == null) //如果是是null
return "null"; "null"
int iMax = a.length - 1; //最大索引值
if (iMax == -1) //如果最大索引值是-1
return "[]"; "[]"
StringBuilder b = new StringBuilder(); //单线程中使用StringBuilder
b.append('['); //追加"["
for (int i = 0; ; i++) { //遍历a数组
b.append(a[i]); //直接将所有数组的元素追加到字符串缓冲区中
if (i == iMax) //如果角标i取到最大索引值
return b.append(']').toString(); //结束: 追加"]"--->转换成String
b.append(", "); //没有最大索引值,追加", "
}
}
ArrayList及增强for嵌套使用
需求:
三个Java班级:每一个班级看成ArrayList
三个班级组成一个大的集合ArrayList<ArrayList<Student>>,
第一个班级存储
高圆圆 22
赵又廷 25
第二个班级存储
张三丰 50
令狐冲 35
第三个班级存储
孙悟空 32
唐僧 40
public class ArrayListTest {
public static void main(String[] args) {
//先创建一个大的集合
ArrayList<ArrayList<Student>> bigArray = new ArrayList<>() ;
//第一个班级
ArrayList<Student> firstArray = new ArrayList<>() ;
Student s1 = new Student("高圆圆",22) ;
Student s2 = new Student("赵又廷",25) ;
firstArray.add(s1) ;
firstArray.add(s2) ;
//将firstArray添加到大集合中
bigArray.add(firstArray) ;
//第二个班级
ArrayList<Student> secondArray = new ArrayList<>() ;
Student s3 = new Student("张三丰",50) ;
Student s4 = new Student("令狐冲",35) ;
secondArray.add(s3) ;
secondArray.add(s4) ;
//将secondArray添加到大集合中
bigArray.add(secondArray) ;
//第二个班级
ArrayList<Student> thirdArray = new ArrayList<>() ;
Student s5 = new Student("孙悟空",32) ;
Student s6 = new Student("唐僧",40) ;
thirdArray.add(s5) ;
thirdArray.add(s6) ;
//将thirdArray添加到大集合中
bigArray.add(thirdArray) ;
//ArrayList<ArrayList<Student>>
//遍历大集合
System.out.println("学生信息是:\t");
for(ArrayList<Student> array:bigArray){
//每一个ArrayList集合里面存储的学生对象
for(Student s: array){
System.out.println(s.getName()+"\t"+s.getAge());
}
}
}
}
ArrayList 和 选择排序思想 实现元素去重
使用List<String>,使用ArrayList具体的子类,
添加重复的String类型数据,保证元素唯一(不能新建集合)
1)接口多态:List接口指向 ArrayList 或者创建具体子实现类ArrayList<String>
2)存储重复的String
3)遍历List ,获取到每一个元素
4)可以借助选择排序的思想:
使用第一个角标对应的元素依次和后面的元素比较,将后面的元素删除,角标--
public class ArrayListTest {
public static void main(String[] args) {
//创建List:可以重复
List<String> list = new ArrayList<>() ;
list.add("hello") ;
list.add("hello") ;
list.add("world") ;
list.add("hello") ;
list.add("javaee") ;
list.add("javaee") ;
list.add("android") ;
list.add("android") ;
list.add("ios") ;
list.add("ios") ;
//List集合:特有遍历方式 : size()获取集合长度 + list集合对象.get(角标)--->获取元素
//选择排序的思想
for(int x = 0 ; x < list.size()-1; x++){ //比较次数
//获取到了所有元素
//使用第一个角标对应的元素依次和后面的元素比较,将后面的元素删除,角标--
for(int y = x +1 ; y < list.size() ; y ++){
if(list.get(y).equals(list.get(x))){ //自定义类需重写equals和hashCode方法
//将后面的元素干掉
list.remove(y) ; //通过角标删除元素
y-- ;
}
}
}
//遍历集合
for(String s:list){
System.out.println(s);
}
}
}
ArrayList_Login_Register 登录注册功能实现
接口实现:
public class UserDaoImpl implements UserDao {
//静态实例
private static List<User> list = new ArrayList<>() ;
//登录和注册的时候,需要使用同一个集合,这个集合被共用
/* static{
List<User> list = new ArrayList<>() ;
}*/
/**
* 这个功能,用户登录功能
* @param username 键盘录入 用户名
* @param password 键盘录入的密码
* @return 返回true,登录成功;否则,登录失败
*/
@Override
public boolean isLogin(String username, String password) {
System.out.println(list); //测试
//假设思想
boolean flag = false ;//false:不成功
//遍历List集合,取数据
//增强for
if(list!=null){ //防止空指针异常
for(User u :list){
//判断如果当前键盘录入的username和集合中的包含的用户的用户名一致,
// 同时 键盘录入的密码和集合中包含的用户的密码一致,return true
if(username.equals(u.getUsername()) && password.equals(u.getPassword())){
flag = true ;
break ;
}
}
}
return flag ;
}
/**
* 这个功能是用户注册功能
* @param user 需要注册的用户
*/
@Override
public void register(User user) {
//创建一个List集合,存储用户
// List<User> list = new ArrayList<>() ;
list.add(user) ;
}
/* @Override
public List<User> findAll() {
for(User user:list){
System.out.println(user);
}
return list;
}*/
}
测试类:
while(true){
//给出一些选项
System.out.println("-----------------------欢迎访问xxx用户管理系统--------------------------") ;
System.out.println("1,登录 2,注册, 3,退出");
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
System.out.println("请输入您的选择器:") ;
String choiceNum = sc.nextLine() ;
//接口多态:
UserDao ud = new UserDaoImpl() ; //使用注册和登录功能
switch (choiceNum){
case "1":
System.out.println("-----------------欢迎进入登录界面-------------------------");
//输入登录的用户名和密码
System.out.println("请您输入登录的用户名:") ;
String username = sc.nextLine() ;
System.out.println("请您输入登录的密码:") ;
String password = sc.nextLine() ;
//调用登录功能
boolean flag = ud.isLogin(username, password);
if(flag){
System.out.println("恭喜您,登录成功!") ;
System.out.println("进入后台管理系统") ;
System.exit(0) ;
}else{
System.out.println("对不起,用户名或者密码输入错误!");
}
break ;
case "2" :
System.out.println("-----------------欢迎进入注册界面-------------------------");
//录入用户名和密码,调用用户的注册功能
System.out.println("请输入用户名:") ;
String name = sc.nextLine() ;
System.out.println("请输入密码:") ;
String pwd = sc.nextLine() ;
//封装用户数据
User user = new User() ;
user.setUsername(name) ;
user.setPassword(pwd) ;
//调用注册功能
ud.register(user) ;
System.out.println("恭喜您,注册成功!");
break ;
case "3":
default:
System.out.println("谢谢使用,欢迎下次再来,再见!");
//break ;
System.exit(0) ; //终止jvm了
}
}
LinkedList
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") ;
//删除
System.out.println(link.removeFirst()) ;
System.out.println(link);
//获取
System.out.println(link.getFirst());
System.out.println(link.getLast());
}
}
LinkedList集合应用场景
Vector
Vector:底层数组,查询快,增删慢,线程安全的,执行效率低!
Vector集合的特有功能:
1、 遍历方式:Collection的Object[] toArray()
2、 Collection的Iterator iterator()
3、List接口提供的 size()+get(int index)
4、 List接口提供的ListIterator listiterator()
5、特有遍历方式
public Enumeration<E> elements()--->相当于集合的迭代器
Enumeration接口:枚举组件
boolean hasMoreElements()---->相当于boolean hasNext()
E nextElement() ---->相当于E next()
public E elementAt(int index)--->相当于List的get(int index)+size方法相结合
6、增强for
添加:
public void addElement(E obj)--->相当于List的add()
public E elementAt(int index)--->相当于List的get(int index)
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");
// 遍历方式1:
//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);
}
// 遍历方式2:
//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);
}
// 遍历方式3:
for(String s:v){
System.out.println(s);
}
Set接口
Set接口特点:
无序(存储和取出不一致),不能保证迭代次序,但是可以唯一
实现子类: HashSet<E> : 存储和取出,保证元素唯一。自定义类型必须重写HashCode和equals方法,保证自定义类的对象唯一
---底层是HashMap实例(哈希表)
实现子类: TreeSet<E> : 存储和取出,同时需要进行排序的取出
---底层是依赖TreeMap实例(红黑树结构)
HashSet<String> hs = new HashSet<>() ;
hs.add("hello") ;
hs.add("hello") ;
hs.add("hello") ;
hs.add("world") ;
hs.add("world") ;
hs.add("world") ;
//遍历
for(String s:hs){
System.out.println(s);
}
HashSet
使用HashSet存储一些学生(姓名,年龄),让你保证学生对象唯一
自定义类型必须重写HashCode和equals方法,保证自定义类的对象唯一
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) ;
hs.add(s1) ;
hs.add(s2) ;
hs.add(s3) ;
hs.add(s4) ;
hs.add(s5) ;
for(Student s:hs){
System.out.println(s.getName()+"---"+s.getAge());
}
HashSet集合的add方法源码
public class HashSet<E> implements Set<E>{
//transient:io流 :map属性不参与序列化(io流相关的)
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public HashSet() {
//创建了一个HashMap集合
map = new HashMap<>();
}
public boolean add(E e) { //"添加的那些元素"
//map集合的添加方法put(k,v)
//e:那些元素,
return map.put(e, PRESENT)==null;
}
}
//HashMap集合
class HashMap<K,V> implements Map<K,V>{
public V put(K key, V value) { //key:传过来的元素,v是常量
return putVal(hash(key), key, value, false, true);
}
//1)"hello","hello","hello","world"...
static final int hash(Object key) { //将key那些元素传进来
int h; //初始化h
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//2)执行putVal()
//jdk8以后:数组+链表+红黑树结构
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
//当链表结构取到7的时候,开始进行"树化"操作
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
}
HashSet集合依赖于HashMap---->间接与hash()---->依赖于hashCode(),put()方法--->equals方法
存储String类型,字符串重写过来equals和hashCode(),元素唯一!
TreeSet
TreeSet<E>有两种排序方式:
自然排序:public TreeSet():使用自然排序,当前里面存储的类型必须实现Comparable
比较器排序:
TreeSet<String> ts = new TreeSet<>() ; //使用TreeSet的无参构造方法,默认使用自然排序
ts.add("world") ;
ts.add("java") ;
ts.add("abc") ;
ts.add("bcd") ;
ts.add("defg") ;
ts.add("defg") ;
ts.add("wyz") ;
for(String s:ts){
System.out.println(s);
}
TreeSet自然排序
自然排序:TreeSet<E>() 无参构造方法
使用自然排序,当前里面存储的类型必须实现Comparable,重写compareTo方法
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) ;
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
for(Student s:ts){
System.out.println(s.getName()+"---"+s.getAge());
}
public class Student implements Comparable<Student>{//实现接口Compareable
//重写compareTo方法
@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;
}
TreeSet的add方法源码
class TreeSet<E> implemnts Set{
private transient NavigableMap<E,Object> m;
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
}
class TreeMap<K,V> implements NavigableMap<K,V>{
public V put(K key, V value) { //K key---->s1---s8学生对象 类型Student
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths //比较器排序/自然排序
Comparator<? super K> cpr = comparator; //比较器排序
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException(); //元素null,空指针异常
@SuppressWarnings("unchecked") //压制警告
//将key的类型
<?>:任意Java类型
<? extends E> 向下限定 E这个类型或者它的子类
<? super E>:向上限定 E这个类型或者它的父类
//K--->Student类型--->
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left; //左子节点
else if (cmp > 0) //右子节点
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
}
要进行自然排序,TreeSet存储类型必须实现接口Compareable接口,重写compareTo方法,否则报错
List和和Set集合的区别
1)是否有序
List存储和取出一致,有序的
Set存储和取出不一致,不能保证迭代次序---->默认使用HashSet--->HashMap集合
2)是否重复
List可以允许元素重复
Set集合中存储的元素唯一
3)具体实现类的数据结构不同
List集合--->ArrayList/Vector:底层数据结构:数组
LinkedList底层数据结构:链表
Set集合---->HashSet基于HashMap实例(底层哈希表)
TreeSet基于TreeMap的实例(底层是一种红黑树(自平衡的二叉树)结构)
TreeSet集合存储自定义类型如何实现自然排序
TreeSet集合要实现自然排序,使用无参构造方法,而且需要保证TreeSet存储的类型必须实现Compareable接口中的compareTo方法(T t)
大部分常用了String,Character,Integer..等等都会实现Compareable接口,完成自然升序排序
class Student implements Compareable<Student>{
//属性私有化
//setXXX(xx)/getXXX()
public int compareTo(Student s){
//需要按照主要条件排序
//自己分析次要条件
return 结果;
}
}
HashSet集合存储自定义类型,如何保证元素唯一
HashSet集合保证自定义类型的元素唯一:
add方法--->依赖于HashMap的put方法---->putVal()方法
--->间接依赖于Object的hashCode()和equals方法;
当前自定义类型必须重写Object的equals和hashCode,保证元素唯一
`