目录
Object
Object是所有java对象的父类。
它有两个重要且常用的方法
equals():用于比较两个对象是否"相等",默认是比较内存地址。可以通过重写方法来自定义规则。
public boolean equals(Object obj) { return (this == obj); }
toString():用于返回对应对象的字符串表示,默认为:类名+@+哈希值
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
hashCode():用于返回对象的内存地址,不同的对象有不同的hashCode值,也可能存在不同对象hashCode值相同,这是一个本地方法。
public native int hashCode();
- 当一个类没有明确其父类时,默认其父类时object。
- Object是所有类的顶级父类。
Arrays
-
数组工具类,数组工具类是围绕这数组来进行操作的,所有复杂的数组类的内部几乎都离不开这个工具类。
-
数组工具类的所有方法都是静态方法,都可以通过类名来直接调用。
-
数组工具类操作数组的基本类型,int,long,double,float,char,boolean,short,object,byte数组类型,而String[]类型的数组本质是对字符类型操作的数组。
常用方法
- Arrays.toString(Array[] a):打印数组
- Arrays.copyOf(Array[] a,int):拷贝指定大小数组。
- Arrays.sort(Array[] a):排序数组。
- 默认从小到大排序
- 默认字母大写先排序
- Arrays.sort(strArray, String.CASE_INSENSITIVE_ORDER):忽略大小写排序
- Arrays.sort(strArray, Collections.reverseOrder()):反向排序
- Arrays.equals():比较数组元素是否相等
- Arrays.fill():填充数组
Arrays.copyOf()这个函数在java中十分重要,很多和数组操作的工具类都使用了大量的Arrays。比如String,集成了大量的Arrays的方法操作。
String
创建数组的两种方式
String的的底层维护了字符数组,在源码中,char类型的数组是String类实现各种操作的基础和核心,因为String被final修饰为常量类型,所以它的值将保存在一个常量池中维护。
public final class String{
private final char value[];
}
一. 传入字符数组
char[] value = {'a','b','c'}; String s1 = new String(value);
它的底层是这样做的,将数组进行直接的复制
public String(char value[]) { this.value = Arrays.copyOf(value, value.length); }
二. 通过引号创建
String s2 = "hello";
先创建引用s2,并在常量池中寻找是否有equals(“abc”),
如果没有,将"abc"放入常量池中,并令s2指向它。
如果有,则将引用指向常量池中的地址。
三. 通过new创建
String s3 = new String("abc");
其底层为是这样的
public String(String original) { this.value = original.value; this.hash = original.hash; }
经典面试题
String到底创建了几个对象
// 若”a“在常量池中不存在,创建一个”123“对象放入常量池中 // 若常量池中存在,则引用指向常量池的地址,不创建对象 String a = "a" // 若a1在常量池中不存在,new指令强制在堆中创建一个对象,并且在常量池也创建有一个对象。 String a1 = new String("ab") // 字符串底层维护,自动拼接为"ab" String a2 = "a" + "b" // 字符串会创建StringBuilder,调用其append()方法,共有"ab",StringBuffer,”abab“三个新对象(若常量池都不存在)。 String a3 = "a" + "b" + a2 // 共创建StringBuilder,"aba",StringBuilder,"abab"四个对象。 String a4 = a2 + "a" + "b"
面试题
1.String s1 = "a" +"b"+"c"; //1个对象 2. String s2 = "a"; //1个对象 String s3= s2 +"bc"; //3个对象 3.String s4 = new String("你") + s2 + "b"; //5个对象 -----------------下面代码与上面代码没有联系------------------- 1.String s6 = "a"; 2.String s7= "b" +"c" + s6; //3个对象 3.String s8= s6 + "d" +"f" ; //4个对象 4.String s9= "ab" + "cd" + s6 + "b" +"c" //5个对象
String的常用方法
equals():判断两个值是否相等,当地址不等时,则逐一比较char字符的值
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
toCharArray():将字符串转变为字符数组。
public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}
split():使用指定字符切割为字符数组
String s3 = "jifjsif-sjfidfjsdsi-sdfjisdj";
String[] s = s3.split("-");
**valueOf(data):**返回字符串,是一个静态方法。
int i = 1;
String.valueOf(i);
System.out.println(i);
trim():去掉首尾两端的空格
replace(Char old, Char new):指定字符代替字符串中的指定字符
toString():返回一个字符对象。
charAt():根据下标查看字符。
concat():字符串拼接。
substring():截取子串,如果参数有两个左闭右开[1,5)。
length():查看字符串的长度。
lastIndexOf():某个字符最后一次出现的位置。
startsWith()-判断是不是以参数开头。
endsWith()–判断是不是以参数结尾。
toUpperCase()-变成全大写。
toLowerCase()-变成全小写。
String类中的+重载
Java本身是不支持运算符重载的,但是String的+是唯一一个实现运算符重载的方法。
String str = "abc"+"def";
在这一步中,常量池会对这个字符串进行优化,直接将abcdef保存在常量池中。并将String类型的引用str指向常量池中的值。
String str = "abc";
String str2 = str+"def";
这个时候,编译器为新建StringBuilder执行这么一段方法
new StringBuilder(str).appand("def").toString()
底层利用StringBuilder的方法来提高效率,避免使用new的方式来实现。
在这个时候,如果我们有频繁的字符串拼接的话,我们应该手动的新建一个StringBuilder对象,以避免StringBuilder重复创建影响效率。
StringBulider和StringBuffer
- StringBuilder和StringBuffer一样,是用来操作字符数组的。
- 两个类都是AbstractStringBuilder的实现类。其底层也是实现了对字符数组的维护。
常用方法
它的一些常用方法和String的常用方法相差不大,只是因为String是final类,并且实现了一些重载方法,对于一些专有方法进行说明
append(str):追加,实现对字符串的追加。
reverse():字符串反转。
insert():在指定位置插入字符串。
toString():返回当前字符串。
setLength():设置长度。
charAt():根据下标获取值。
delete(int start, int end):删除指定位置的值。
replace(int start, int end, String str):用指定字符串更换指定位置值。
String substring(int start, int end):切割指定位置字符,左闭右开。
insert():插入值。
注意
-
StringBuilder是jdk1.5之后的新特性
-
StringBuilder是线程不安全的,StringBuffer是线程安全的,在StringBuffer操作字符时,会为当前方法加入一个
synchronized
。public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
-
String是线程安全的,因为常量池存在于方法区,被所有线程共享,不存在数据不安全问题。
-
在单线程操作大量数据,推荐使用StringBuilder,在多线程操作大量数据,推荐使用StringBudffer。
经典面试题:字符串反转
面试官:你简单说一下字符串反转怎么做
方法一:新建一个StringBuffer对象并传入字符串,使用其reverse方法反转,再使用toString方法为原引用赋值。
String a = "abc"; StringBuffer buffer = new StringBuffer(a); buffer.reverse(); a = buffer.toString();
方法二:使用toCharArray()方法将其转换为数组,然后使用for循环进行转换。然后使用valueof()方法进行字符串转换。
String a = "abc"; char[] s1 = a.toCharArray(); for (int i = 0; i < s1.length/2; i++) { char number = s1[i]; s1[i] = s1[s1.length-i-1]; s1[s1.length-i-1] = number; } a = String.valueOf(s1);
Iterator
Iterator 常用于迭代集合中的元素。主要有三个方法
(1) 使用next()获得序列中的下一个元素。
(2) 使用hasNext()检查序列中是否还有元素。
(3) 使用remove()删除迭代器最后一个元素并删除。