文章目录
一、 数组
1. 数组简介
- 数组是一组数据的集合
数组作为一种引用类型,申请的空间在堆中
- 数组元素的类型可以是基本类型,也可以是引用类型,但同一个数组只能是同一种类型
- 数组作为对象,
数组中的元素作为对象的属性,除此之外数组还包括一个成员属性 length, length 表示数组的长度
数组的长度在数组对象创建后就确定了,就无法再修改了
- 数组元素是有下标的,下标从 0 开始,也就是第一个元素的下标为 0,依次类推最后一个元素的下标为n-1,我们可以通过数组的下标来访问数组的元素
2. 如何在数组中存放多个数据类型?
可以利用多态的思维,将数组定义成父类,则数组中可以存放子类,当然最大的父类是Object!!!!
public class Test {
public static void main(String[] args){
Object [] a = new Object[5];
a[0] = 1;
a[1] = 1.1;
a[2] = true;
a[3] = "123";
a[4] = '1';
System.out.println(Arrays.toString(a));//[1, 1.1, true, 123, 1]
}
}
3. 数组的初始化方式有几种?
- 使用 new 操作符来创建数组,再初始化 ,type[] 变量名 = new type[数组中元素的个数]
- 通过大括号的方式直接初始化,type[] 变量名 = new type[]{逗号分隔的初始化值};
4. 数组如何比较?
数组内容的比较可以使用 equals()方法吗?
public class ArrayTest06
{
public static void main(String[] args)
{
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(a.equals(b));//false
}
}
数组是引用类型,使用equals()方法调用的是Object的equals()方法,执行的依然是==,也就是地址比较。
解决方案:
- 自己写工具类,先判断是否为空,再判断长度是否相同,最后顺序比较内容
public class ArrayEqualsTest07
{
public static boolean isEquals(int[] a, int[] b)
{
if( a == null || b == null )
{
return false;
}
if(a.length != b.length)
{
return false;
}
for(int i = 0; i < a.length; ++i )
{
if(a[i] != b[i])
{
return false;
}
}
return true;
}
public static void main(String[] args)
{
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(isEquals(a,b));
System.out.println(Arrays.equals(a,b));
}
}
- 利用Arrays.equals()方法比较
5. 数组的扩容及优化
1、数组长度不可变,那么数组怎么扩容呢?
- 原数组满了之后,可以新建一个新的容量更大的数组,将原数组中的数据拷贝到新数组中,原数组对象被 GC 回收,以后向新数组中存储数据。这就是数组的扩容。
2、数组扩容涉及到数组的拷贝,数组拷贝会耗费大量的资源。
3、数组怎么优化,怎么样可以提高效率?
- 创建数组的时候,预先估计数组中存储的元素个数,给定初始化容量,减少数组的扩容次数,减少数组的拷贝,提高程序的执行效率
6. 数组的拷贝
public class ArrayTest08
{
public static void main(String[] args){
int[] src = {5,6,9,8,2,3,6,7,5,6,4,2,3,8,9};
int[] dest = {1,1,1,1,1,1,1,1,1};
//这里调用的是自己写的 arraycopy
//arraycopy(src,3,dest,1,4);
//调用 JDK 库中 System 类中提供的 arraycopy 方法
System.arraycopy(src,3,dest,1,4); //底层是 native 方式
//遍历
for(int i=0;i<dest.length;i++){
System.out.println(dest[i]);
}
}
/** * 自定义的数组拷贝的方法 * @param src 原数组 * @param srcPos 原数组开始拷贝的下标 * @param dest 新数组 * @param destPos 新数组开始拷贝的下标 * @param length 拷贝的元素个数 */
public static void arraycopy(int[] src,int srcPos,int[] dest,int destPos,int length){
for(int i=srcPos;i<srcPos+length;i++){
//dest[destPos] = src[i];
//destPos++;
dest[destPos++] = src[i];
}
}
}
7. 数组的排序
8. 数组的查找
二、 常用类
1. Arrays工具类
sort()
binarySearch()
2. String
String 类是不可变类
不可以通过继承去重新定义方法,可以定义一个类,包含String类,然后再增强或者实现。
public class StringTest02 {
public static void main(String[] args) {
String s1 = "abc";//指向的常量池
String s2 = "abc";//指向的常量池
String s3 = new String("abc");//指向的是堆内存
System.out.println("s1==s2, " + (s1==s2));//true
System.out.println("s2==s3, " + (s2==s3));//false
System.out.println("s2 equlas s3," + (s2.equals(s3)));//true
}
}
- 当通过new关键字构建的时候,会在堆内存创建一个对象,在常量池创建一份对象,并且变量指向的是堆中对象的地址
定义String时,尽量使用双引号定义,这样可以节约空间,重复利用
注意事项
因为 String 是不可变对象,如果多个字符串进行拼接,将会形成多个对象,这样可能会造成内存溢出,会
给垃圾回收带来工作量,如下面的应用最好不要用 String
常用方法
- endsWith:判断字符串是否以指定的后缀结束
- startsWith,判断字符串是否以指定的前缀开始
- equals, 字符串相等比较,不忽略大小写
- equalsIgnoreCase,字符串相等比较,忽略大小写
- indexOf,取得指定字符在字符串的位置
- lastIndexOf,返向最后一次字符串出现的位置
- length,取得字符串的长度
- replaceAll, 替换字符串中指定的内容
- split,根据指定的表达式拆分字符串
- substring,截子串
- trim,去前尾空格
- valueOf,将其他类型转换成字符串
3. String、StringBuffer 和 StringBuilder
可变性
- String类定义了final char数组,所以数据是不可变的
- StringBuffer 和 StringBuilder定义都只是char数组,数据是可变的
线程安全性
- String是不可变的,所以线程安全
- StringBuffer内部的方法是加了同步锁,所以线程安全
- StringBuilder没有加锁,所以线程不安全
线程安全 != 保证拼接顺序
StringBuffer的线程安全只是保证了在一次append()中不会有其他线程进入
性能
- String是不可变的,每次更改都需要重新创建一个新的对象,所以性能很差
- StringBuffer因为加锁的缘故,性能比StringBuilder略差10%~15%左右
4. 基本类型对应的包装类
为了保证线程安全,包装类都是不可变类型。
基本类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
-
除了 Boolean 和 Character 外,其它的包装类都有 valueOf()和 parseXXX 方法 ,同时都是number的子类
-
自动装箱和拆箱是JDK1.5之后提供的,方便基本类型与包装类之间的转换
String、 int、 Integer 之间的转换
public class Test {
public static void main(String[] args) {
//String + Integer
Integer a = new Integer("123");
String b = Integer.toString(123);
//String + int
int c = Integer.parseInt("123");
String d = String.valueOf(c);
//int + Integer
Integer e = 123;
int f = e.intValue();
}
}