Java数组及常用类

文章目录

    • 一、 数组
      • 1. 数组简介
      • 2. 如何在数组中存放多个数据类型?
      • 3. 数组的初始化方式有几种?
      • 4. 数组如何比较?
      • 5. 数组的扩容及优化
      • 6. 数组的拷贝
      • 7. 数组的排序
      • 8. 数组的查找
    • 二、 常用类
      • 1. Arrays工具类
        • sort()
        • binarySearch()
      • 2. String
        • String 类是不可变类
        • 注意事项
        • 常用方法
      • 3. String、StringBuffer 和 StringBuilder
        • 可变性
        • 线程安全性
        • 性能
      • 4. 基本类型对应的包装类
      • 5. 数字类
        • DecimalFormat
        • BigDecimal
      • 6. Random
      • 7. Enum

一、 数组

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();
    }
}

5. 数字类

DecimalFormat

BigDecimal

6. Random

7. Enum

你可能感兴趣的:(面试题总结,java)