Review-Day3


复习day3

1. String(底层原理,创建方式,常量池)

  • 底层原理

    String类的一个最大特性是不可修改性,而导致其不可修改的原因是在String内部定义了一个常量数组final char数组,因此每次对字符串的操作实际上都会另外分配,分配一个新的常量数组空间

  • 创建方式

    String的创建方式一般有两种,一种是常见的new String(),如String s1 = new String(“ab”),另一种是字面量赋值,如String s2 = “ab”。第一种对象的创建方式会创建两个对象,一个是new创建的对象,一个是在字符串常量池中创建”ab”字符串。第二种方式是直接在字符串常量池中创建”ab”字符串(前提是字符串常量池没有该字符串,有的话,直接把该引用赋值给s2)

  • 常量池(元空间的方法区里)

    在JVM底层实际上会自动维护一个对象池(字符串常量池) 如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存 到这个对象池之中. 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用 ,如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。

2. String各种比较

“==”判断的是地址值,判断引用是否指向堆内存的同一块地址;equals()方法判断的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

/**
 * 本类用来演示: 字符串的各种比较
 */
public class StringCompare {
    public static void main(String[] args) {
        //s1默认指向的是堆里面的字符串对象
        String s1 = new String("abc");
        String s2 = "abc";
        System.out.println(s1 == s2);//false

        //intern()强制让s1指向串池的对象
        System.out.println(s1.intern() == s2);//true

        String s3 = "b";
        String s4 = "a" + s3;//产生一个StringBuilder对象
        String s5 = "a" + "b";//因为此处的"a"和"b"就是字符串常量
        //jvm对待字符串常量的拼接 - "a"和"b"的拼接
        //当成"ab"的整体,直接扔到常量池中.

        System.out.println(s4 == s5);//false

        //字符串使用final修饰
        final String s6 = "b";
        //"a"+s6 => "ab"扔到常量池,没有产生新的对象.
        String s7 = "a" + s6;
        System.out.println(s5 == s7);//true


        String x1 = new String("abc");
        String x2 = new String("abc");
        System.out.println(x1 == x2);//false

        System.out.println(x1);

        //希望字符串的值是一样的,就希望返回true
        System.out.println(x1.equals(x2));//true

    }
}

3. String ,StringBuilder, StringBuffer区别

三者之间都是使用final修饰的,都是不可被继承的

String: 字符串不可变,适用于字符串内容不经常发生改变的时候

StringBuilder: 字符串可变,适用于字符串内容经常发生改变的时候,适用于单线程(线程不安全),在单线程中,执行效率较高

StringBuffer:字符串可变,适用于字符串内容经常发生改变的时候,适用于多线程(线程安全)

4. 算法题

删除指定字符串

/**
     * 根据字符串到原来的字符串中进行删除操作 - 操作的不是原来的字符串,不断返回一个新的字符串.
     * @param oldStr
     * @param target
     * @return
     */
public static String delByStr(String oldStr,String target){
    //1. 递归出口
    if(!oldStr.contains(target))
        return oldStr;
    //2. oldStr中仍然包含target
    //找到target字符串在oldStr字符串中的下标位置.
    //bcbcabca  -> ca
    int startIndex = oldStr.indexOf(target);//返回target在oldStr中第一次出现的下标位置
    int endIndex = startIndex+target.length();//5
    //String类型转换成StringBuilder类型 - delete(int start,int end);//[start,end)
    StringBuilder builder = new StringBuilder(oldStr);
    StringBuilder result = builder.delete(startIndex,endIndex);//bcbbca
    return delByStr(result.toString(),target);
}

找出俩个字符串中的最大长度的公串

public static String findCommonStr(String str1,String str2){
    //abcbcbcaaaffffff
    //fdfdffffffooobcbcbcqqq

    //定义一个变量
    int len = 0;

    //定义StringBuilder对象,用来保存所有的最大长度的公串
    StringBuilder builder = new StringBuilder();

    //假设str1的长度比str2的长度小.
    for (int i = 0; i < str1.length(); i++) {
        for (int j = i+1; j <=str1.length(); j++) {
            //获取每个子串的各种组合
            String subStr = str1.substring(i,j);
            //将每个子串的长度
            int length = subStr.length();
            if(str2.contains(subStr) && length>len){
                //清空builder
                builder.delete(0,builder.capacity());
                builder.append(subStr+" ");
                len = length;
            }else if(str2.contains(subStr) && length==len){
                builder.append(subStr+" ");
            }
        }
    }
    return builder.toString();
}

统计字母个数

/**
 * @Description: 统计字符串, 每个字符出现的次数
 * @Auther: zhugefeng
 * @Date:2021/7/30 12:54
 **/
public class CountStrDemo {
    public static void main(String[] args) {
        String str = "ahfdfjdkfjsdafsed";
        count(str);
    }

    private static void count(String str) {
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < str.length(); i++) {
            if (map.containsKey(str.charAt(i))) {
                Integer count = map.get(str.charAt(i));
                map.put(str.charAt(i),count++);
            } else {
                map.put(str.charAt(i), 1);
            }
        }
        List<Map.Entry<Character,Integer>> sortList = new ArrayList<>();
        //排序
        Set<Map.Entry<Character,Integer>> set = map.entrySet();
        Iterator<Map.Entry<Character,Integer>> iter =set.iterator();
        while (iter.hasNext()){
            sortList.add(iter.next());
        }
        sortList.sort((c1,c2)->c2.getValue()-c1.getValue());
        for (Map.Entry<Character,Integer> e : sortList){
            System.out.println(e.getKey()+":"+e.getValue());
        }
    }
}

5. Integer底层原理,IntegerCache 范围

Integer底层原理

在Integer类内部定义了一个私有的静态类IntegerCache,用来实现Integer的缓存常量池。

该缓存的作用是为了节省内存,提高性能。
在给一个Integer对象直接赋一个int类型的值得时候:Integer num = 100;

Java会通过自动装箱机制将int类型值转为Integer类型。自动装箱是指在编译时期编译器自动调用包装类型中的valueOf()方法,进行自动的转换。

针对[-128,127]这个范围内的值,Integer会通过复用对象的方式来提升内存的使用率,减少新对象的生成。

如果在[-128,127]之间,那么直接返回内部的缓冲数组中的数据,如果不在这个范围,返回一个新的Integer对象.

6. Integer各种比较

1、包装类Integer跟基本类型int的比较
直接取出包装类事例所包装的数值进行比较。
Integer it1 = 2;
Integer it3 = new Integer(2);
int i1 = 2;
System.out.println(it1 == i1);//true
System.out.println(it3 == i1)//true

如果是两个包装类进行比较会有以下几种情况
(1)包装类的实例实际上是引用类型,所以比较的是对象地址,两个不同的对象比较,false
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false

Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false
-----------------------------------------------------------------------------------------------

[-128,127]之间,那么直接返回内部的缓冲数组中的数据,
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true

Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false

7. Integer和int区别

(1)Integer是int的包装类;int是基本数据类型;

(2)Integer变量必须实例化后才能使用;int变量不需要;

(3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;

(4)Integer的默认值是null;int的默认值是0

(5) Integer支持泛型,int不支持

8. 自动装箱与拆箱

装箱:将基本类型—转换成—对应的包装类;

拆箱:将包装类型—转换成—基本数据类型;

Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。

9. 5个运行异常 5个非运行异常

运行时异常

ClassCastException 类转换异常

illegalArgumentException 非法参数异常

IndexOutOfBoundsException 下标越界异常

NullPointerException 空指针异常

java.util.NoSuchElementException - 不存在此元素

java.lang.ArithmeticException - 计算异常 - 分母为0

非运行时异常

java.io.IOExcetion - IO流异常

java.sql.SQLException - SQL异常

java.text.ParseException - 解析失败异常 - 字符串的模板和pattern不匹配

InterruptedException - 中断异常 - Thread.sleep(1000);

java.lang.CloneNotSupportedException - 不允许被clone.

10. 5个String常用api

indexOf()返回指定字符串在该字符串出现的序列

startsWith()判断该字符串是否以指定字符开始

endsWith()判断该字符串是否以指定字符串结尾

concat() 将指定字符串连接在该字符串的结尾

length()返回字符串的长度

substring(int start,int end) // 截取字符串 从start开始 ,到end-1为止 生成一个新串返回

trim 去掉字符串前后的空格

charAt(index)返回下标对应的字符


文章作者: 码农耕地人
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 码农耕地人 !
  目录