java知识点整理

时间:2022-11-17 15:22:35

一、String类

  1. 字符串存储在内存的常量池中,若一个字符串在内存中已经存在,则不会重新开辟空间
    例如:String s1 = “abc”; String s2 = “abc”;String s3 = new String(“abc”);
    s1 == s2, true s1 == s3, false

  2. 字符串常见的操作:
    a. 获取
    a.1字符串的长度:int length();
    a.2获取字符:char charAt(int index); 访问到字符串中不存在的角标时返回StringIndexOutOfBound异常
    a.3根据字符获取该字符在字符串中位置:int indexOf(int ch):返回ch在字符串中第一次出现的位置 int indexOf(int ch, int fromIndex);
    a.4 int lastIndexOf(int ch);
    b. 判断
    b1 字符串是否包含某一个子串 boolean contains(str)
    b2 字符串中是否有内容 boolean isEmpty(): 判断长度是否为0
    b3 字符串是否以指定内容开头 boolean startsWith(str)
    b4 字符串是否以指定内容结尾 boolean endsWith(str)
    b5 字符串的内容是否相同 boolean equals(str)。复写了Object类中equals方法。
    b6 判断内容是否相同,并忽略大小写 boolean equalsIgnoreCase(str)
    c. 转换
    c1 将字符数组转成字符串
    构造函数:String(char[]) String(char[], offset, count)
    静态方法:static String copyValueOf(char[]) static String copyValueOf(char[] data, int offset, int count) static String valueOf(char[]);
    c2 将字符串转成字符数组
    c3 将字节数组转成字符串
    c4 将字符串转成字节数组
    c5 将基本数据类型转成字符串

注:字符串和字节数组在转换过程中,可以指定编码表

d. 替换 String replace(oldchar, newchar)
e. 切割 String[] split(regex)

获取字符串最大相同子串:

public static String getMaxSubString(Sring s1, String s2){
for(int I = 0; I < s2.length(); i++){
for(int j = 0, z = s2.length()-i; z < s2.length()+1; j++, z++){
String tmp = s2.subString(j, z);
if (s1.contains(tmp))
return tmp;
}
}
return null;
}

二、StringBuffer和StringBuilder

StringBuffer: 字符串缓冲区
是一个容器,1. 长度可变化 2. 可以字节操作多个数据类型 3. 最终可通过toString()方法变成字符串

StringBuilder: 与StringBuffer一样,但是在1.5版本后才出现,但是StringBuilder线程不安全。因为StringBuffer每次操作都需要判断锁,而StringBuilder没有锁,所以效率要高很多。单线程用StringBuilder,多线程用StringBuffer或者StringBuilder自己加锁。

三、基本数据类型包装类:

byte->Byte short->Short int->Integer long->Long boolean-Boolean double->Double char->Character
整数类型的最大值:Integer.MAX_VALUE

基本数据类型对象包装类的最常见操作:
1. 基本数据类型转字符串
基本数据类型+“”
基本数据类.toString(基本数据类型) 如:Integer.toString(34)
2. 字符串转数据类型
int num = Integer.parseInt(“123”)
long x = Long.parseLong(“123”)
boolean b = Boolean.parseBoolean(“true”)

注:

 Integer m = 127; 
Integer n = 127;
System.out.println(m==n)
Output: true
Integer a = 128; Integer b = 128; 
System.out.println(a==b)
Output: false

在新特性中,若结果在byte范围内的值,若该数值已经存在,则不会开辟新空间

基本数据类型包装类都重写了Object类中的equals()方法,都判断内容是否相等。==是判断是否为同一对象。

四、集合框架

集合和数组区别:数组是固定的,集合是可变的
集合类特点:集合只用于存储对象,集合长度是可变的,集合可存储不同类型的对象

Collection接口抽取出来List接口和Set接口,List接口有三种具体实现方式ArrayList,LinkedList,Vector,set有HashSet和TreeSet
为什么会有这么多容器? 因为每一个容器对数据的存储方式都有不同
这个存储方式称之为数据结构

迭代器:集合取出元素的方式
Iterator it = al.iterator();
hasNext():判断是否有可迭代元素 next():取出下一个元素 remove():移除迭代器返回的最后一个对象
因为每一个容器底层的数据结构不同,所以存取的方式也不同,每个集合的存取方式不足以用一个方法来描述,因此将存取操作封装到一个类中,而这个类就定义在集合的内部,因为元素在集合中,想要操作集合元素,在集合内部操作比较方便。但是存取操作会存在很多共性,比如判断是否有元素和取出元素,于是就把这些共性内容抽取出来,作为一个接口就是iterator接口,由所有内部类去实现该接口,如何获取集合的取出对象呢?对外提供了一个iterator()方法

Collection:
|–List:元素是有序的,元素可以重复,因为该集合体系有索引
|–ArrayList底层用数组数据结构实现。特点:查询速度快,但增删慢。线程不同步
|–LinkedList底层是链表数据结构。特点:增删快,查询慢
|–Vector底层是数组数据结构。1.0出现,元老级别,线程同步(被替代)
|–Set: 元素无序,元素不可重复
|–HashSet底层数据结构是哈希表
|–TreeSet可以对set集合中的元素进行排序,底层数据结构是二叉树

List的特有方法,可以操作角标的方法
增,add(index,element) 删remove(index) 改set(index,element) 查get(index) subList(from,to) listIterator()
若在迭代过程中准备添加或删除元素,iterator迭代器无法完成,List集合中有一个特有的迭代器ListIterator,它是iterator的子接口,改接口只能通过List集合的listIterator方法获取
ListIterator li = al.listIterator() 可以实现在集合遍历过程中的增删改查。

注意:在用迭代器去元素的时候,迭代器取一个元素就要先判断元素是否存在。

将类传入一个ArrayList al中,要判断al中是否包含某个对象,需要在类中重写equals方法,因为Object类中的equals方法默认判断两个对象的地址是否相同。

HashSet如何保证元素唯一?
HashSet在存入元素的时候,先比较hashcode是否相同,如若不同,则直接存入;如若相同,则调用equals方法去比较内容是否相同。
HashSet如何存储自定义对象?
复写Object类中的hashcode方法,用类中的元素值的哈希值进行复写,比如name.hashCode()+age*37,age*37是为了保证唯一性。然后复写Object类中的equals方法。
注意:ArrayList判断元素是否存在和删除元素依赖equals;HashSet判断元素是否存在和删除元素,先判断hashcode是否相同,再依赖equals。

TreeSet存入自定义对象:自定义类要实现Comparable接口,实现里面的CompareTo方法,该接口强制让自定义类具备比较性。排序时,当主要条件相同时,一定要判断次要条件。
TreeSet保证元素唯一性的依据是compareTo方法返回0.
TreeSet排序的第一种方式:让元素具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。
第二种方式:当元素不具备比较性,或者具备的比较性不是所需要的。这时需要让集合自身具备比较性。具体方式:定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。定义一个类,实现Comparator接口,覆盖compare方法。
当两种方式都存在时,以比较器为主。
注意:一定要考虑到主要条件比较完还有次要条件需要比较。

五、泛型

好处:1. 将运行时期出现问题ClassCastException转移到了编译时期,方便于程序员解决问题,让运行时期的问题减少,安全;2. 避免的强制转换的麻烦。

泛型类:
1. 泛型类定义的泛型在整个类中有效,若被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
2. 为了让不同的方法操作不同类型,而且类型不确定,则可以将泛型定义在方法上。
3. 可以在泛型类中定义泛型方法,但是在创建对象时指定的泛型类的类型,和泛型类相同类型的方法需要与指定泛型类类型相同。
4. 注意:静态方法不能访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,需要在静态方法上定义泛型,public static 返回值 XXX(){}

泛型定义在接口上:

class InterImpl<T> implements Inter<T>{
public void show(T t){}
}

泛型限定:(?是通配符,也即占位符)
? extends E:可以接收E类型或E的子类型,上限。
? super E:可以接受E或者E的父类型,下限。
普通的泛型:

public static <T> void XXX(ArrayList<> al){}

或者

public static void XXX(ArrayList<?> al){}

若要限定操作某一类型的子类:

public static void XXX(ArrayList<? extends Person> al){}