zoukankan      html  css  js  c++  java
  • Java字符串与数组

    问题及答案来源自《Java程序员面试笔试宝典》第四章 Java基础知识 4.5字符串与数组

    1、字符串创建与存储的机制是什么?

    Java中字符串声明与初始化主要有两种情况:

    (1)String s1 = new String("abc")与String s2 = new String("abc")语句   

    执行String s1 = new String("abc")语句,字符串池中不存在"abc",则会创建一个字符串常量"abc",

    并将它添加到字符串常量池中,然后new String()会在堆中创建一个新的对象,s1指向堆中的String对象

    紧接着创建String s2 = new String("abc")语句,因为字符串常量池中已经有了字符串常量"abc",所以

    不会再创建"abc",直接new String()在堆中创建一个新的对象,然后使用s2指向这个对象

    s1与s2指向堆中的不同String对象,地址自然也不相同

    (2)String s1 = "abc"语句与String s2 = "abc"语句

    在JVM中存在着一个字符串常量池,其中保存了着很多String 对象,s1,s2引用的是同一个常量池中的对象。

    当创建一个字符串常量时,例如String s1 = "abc",会首先在字符串常量池中查找是否已经有相同的字符串被定义,

    若已经定义,则直接获取对其的引用,此时不需要创建字符串常量"abc",如果没有定义,则首先创建字符串常量

    "abc",然后把它加入到字符串池中,再将引用返回

    例子1:

    String s1 = new String("abc");   //  先查找常量区有无"abc"常量,若无则将其"abc"添加到常量区,再在堆中创建对象,将s1指向堆中的对象

    String s2 = new String("abc");    //  发现在常量区已经有了"abc",在堆中创建对象,将s2指向堆中的对象

    例子2:

    String s1 = "abc";  //  在常量区里面创建一个"abc"字符串对象,s1获取对其的引用

    String s2 = "abc";  //  发现在常量区已经有了"abc",s2直接获取对其的引用

    引申 - 对于String类型的变量s,赋值语句s=null和赋值语句s=""有什么区别?

    s=null,是指s不指向任何一个字符串;s=""中的s指向空字符串

    笔试题 - new String("abc")创建了几个对象?

    一个或两个,如果常量池中原来就有"abc",那么只创建一个对象,否则创建两个对象

    2、==、equals和hashCode有什么区别?

    ==:是运算符,用于比较两个变量是否相等。当比较对象时,比较的是对象在内存中的地址

    equals方法:用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟==的结果一样

    如果一个类没有自己定义equals方法,它默认的equals方法就是使用"=="运算符,也就是在比较两个变量指向

    的对象是否是同一个对象

    hashCode方法:是用来鉴定两个对象是否相等,默认Object类中的hashCode方法返回对象在内存中地址转换成

    的一个int值,所以如果没有重写hashCode()方法,任何对象的hashCode()方法都是不相等的。返回一个离散的int型整数。

    在集合类操作中使用,为了提高查询速度。(HashMap,HashSet等)

    equals方法实际使用:

     1 class Person{
     2     
     3 }
     4 
     5 public class ObjectDemo {
     6     public static void main(String[] args) {
     7         // Person类没有重写equals方法 而Object类中的equals方法是比较两个对象的地址
     8         Person p1 = new Person();
     9         Person p2 = new Person();
    10         System.out.println(p1.equals(p2));            // false
    11         
    12         // String中重写了equals方法  比较的是两个字符串的内容
    13         String s1 = new String("hello");
    14         String s2 = new String("hello");
    15         System.out.println(s1.equals(s2));            // true
    16 
    17         String s3 = "hello";
    18         String s4 = "hello";
    19         System.out.println(s3.equals(s4));            // true
    20     }
    21 }

    java中的数据类型,可分为两类: 

    (1)基本数据类型

    Java中基本数据类型有八种:byte,short,char,int,long,float,double,boolean,

    他们之间的比较,用双等号(==),比较的是他们的值。

    (2)复合数据类型(类)

    当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new

    出来的对象,他们的比较后的结果为true,否则比较后结果为false。 

    在Java的Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,

    但在一些类库当中这个方法被覆盖掉了,如String等,在这些类当中equals有其自身的实现,而不再是

    比较对象的内存地址了

    equals方法和hashCode方法的关系(用于set、map):

    hashCode方法只有在set或map集合中用到

    当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)

    将对象放入到集合中时,首先判断要放入对象的hashCode值与集合中的任意一个元素的hashCode值是否相等,

    如果不相等直接将该对象放入集合中。如果hashCode值相等,然后再通过equals方法判断要放入对象与集合中的

    任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

     

    3、String、StringBuffer、StringBuilder和SringTokenizer有什么区别?

    Java中有5个类可以对字符或字符串进行操作,分别是Character、String、StringBuffer、StringBuilder

    和SringTokenizer,其中Character用于单个字符操作,String用于字符串操作(属于不可变类),而

    StringBuffer也是用于字符串操作(属于可变类)

    Character的API:

    • boolean isDigit(char ch)        确定指定字符是否为数字。
    • boolean isLowerCase(char ch)  确定是否是小写字母字符
    • boolean isUpperCase(char ch)  确定是否大写字母字符
    • char toLowerCase(char ch)     将给定字符转换成大写字符 
    • char toUpperCase(char ch)     将给定字符转换成小写字符 

    String的API:

     1 引用类型String中的方法(4532)
     2 第一组: 判断方法
     3           boolean equals(String str);            // 比较两个字符串的内容是否相等
     4           boolean equalsIgnoreCase(String str);     // 比较两个字符串的内容是否相等(忽略大小写)
     5           boolean startsWith(String subStr);       // 判断某个字符串是否以指定的子串开头
     6           boolean endsWith(String subStr):        // 判断某个字符串是否以指定的子串结尾
     7  
     8 第二组: 获取方法
     9           int length();                           // 获取字符串中字符个数
    10           char charAt(int index);                   // 谋取字符串某一个字符(指定下标)
    11           String subString(int startIndex);              // 从指定下标开始截取字符串,直到字符串末尾
    12           String subString(int startIndex, int endIndex);     // 从指定下标开始截取字符串,到指定下标结束(左闭右开)
    13           int indexOf(String subStr);                    // 获取子串第一次出现的下标
    14   
    15 第三组: 转换方法
    16           String toLowerCase();    // 转成小写串
    17           String toUpperCase();    // 转成大写串
    18           Char[] toCharArray();    // 变成字符数组
    19   
    20 第四组: 其他方法
    21           String trim();                     // 去掉字符串两端的空格
    22           String[] split(String str);        // 切割字符串

    String和StringBuffer的区别:

    String是不可变类,一旦对象创建其值将不能改变,而StringBuffer是可变类,对象创建后值可以改变

    实例化String时可以用赋值也可以用new初始化,而实例化StringBuffer只能用new初始化

    String字符串修改的原理:

    当用String类型来对字符串进行修改时,其实现方法是首先创建一个StringBuffer对象,然后调用StringBuffer的

    append方法,最后调用StringBuffer的toString方法把结果返回

    1 String s = "Hello";
    2 s += " World";
    3 // 以上代码等价于
    4 StringBuffer sb = new StringBuffer(s);
    5 sb.append(" World");
    6 s = sb.toString();

    StringBuilder和StringBuffer:

    StringBuilder也是可以被修改的字符串,它与StringBuffer类似,都是字符串缓冲区,但是StringBuilder

    不是线程安全的,如果只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些

    而StringBuffer在必要时可以对方法进行同步,所以任意特定实例上的操作就好像是以串行顺序

    发生,该顺序与所涉及的每个线程进行的方法调用顺序一致

    因此在只有单线程访问时可以使用StringBuilder,当有多个线程访问时最好用线程安全的StringBuffer

    StringTokenizer:

    StringTokenizer是用来分割字符串的工具类,示例如下:

    1 public class Demo{    
    2     public static void main(String[] args) {
    3         StringTokenizer st = new StringTokenizer("Welcome to our country");
    4         while(st.hasMoreTokens()){
    5             System.out.println(st.nextToken());
    6         }
    7     }    
    8 }

    输出结果:

    Welcome
    to
    our
    country

    总结:

    在执行效率方面,StringBuilder最高,StringBuffer次之,String最低,使用如下:

    • 如果操作的数据量比较小,应优先使用String类
    • 如果是在单线程下操作大量数据应优先使用StringBuilder类
    • 如果是在多线程下操作大量数据应优先使用StringBuffer类

    4、Java中数组是不是对象?

    数组是指具有相同类型的数据的集合,它们一般具有固定的长度,并且在内存中占据连续的空间 

    在C/C++中,数组名只是一个指针,这个指针指向了数组的首元素,没有属性也没有方法

    而在Java中,数组不仅具有自己的属性,还有方法可以调用,故在Java中数组是对象

    每个数组类型都有其对于的类型,可以通过instanceof来判断数据的类型,如下:

     1 public class FindLeftAndRightBigger {
     2     public static void main(String[] args) {
     3         int[] a = {1, 2, 3};
     4         int[][] b = new int[2][3];
     5         String[] s = {"asfd", "saf"};
     6         if(a instanceof int[]){
     7             System.out.println("int[]");
     8         }
     9         if(b instanceof int[][]){
    10             System.out.println("int[][]");
    11         }
    12         if(s instanceof String[]){
    13             System.out.println("String[]");
    14         }
    15     }    
    16 }
    17 // 输出结果:
    18 // int[]
    19 // int[][]

    5、Java数组的初始化方法有哪几种?

    Java数组的初始化方法如下:

     1 // 一维数组声明:
     2 type arrayName[] 或 type[] arrayName
     3 // 二维数组声明:
     4 type arrayName[][] 或 type[][] arrayName 或 type[] arrayName[]
     5 // 数组初始化:可以在声明时直接赋值也可以在之后new
     6 // 注:type既可以是基本数据类型也可以是类
     7 
     8 // 一维数组初始化实例:
     9 int[] a = new int[5];  // 动态创建了一个包含5个整形值得数组,默认值为0   
    10 int[] a = {1, 2, 3};    // 声明一个数组并初始化
    11 
    12 // 二维数组初始化实例:
    13 // Java中二维数组的第二维长度可以不同
    14 int[][] arr = {{1, 2}, {3, 4, 5}};
    15 int[][] arr = new int[2][];
    16 arr[0] = new int[]{1, 2};
    17 arr[1] = new int[]{3, 4, 5};

    注:原生类指未被实例化的类,数组是实例化、被分配空间的类,数组不属于原生类 

    6、length属性和length()方法有什么区别?

    • length属性:获取数组长度
    • length方法:计算字符串长度
     1 public class test{f
     2     public static void testArray(int[] arr){
     3         System.out.println("数组长度为" + arr.length);
     4     }
     5     
     6     public static void testString(String s){
     7         System.out.println("字符串长度为" + s.length());
     8     }
     9     
    10     public static void main(String[] args) {
    11         testArray(new int[]{1, 2, 3});      // 3
    12         testString("hello");            // 5
    13     }    
    14 }
  • 相关阅读:
    [HAOI2015]T2
    bzoj1036:[ZJOI2008]树的统计Count
    苹果树
    poj1151 Atlantis
    1593: [Usaco2008 Feb]Hotel 旅馆
    [JSOI2008]最大数maxnumber
    【HNOI2014】米特运输
    【HNOI2013】数列
    Luogu5221 Product
    【CQOI2014】数三角形
  • 原文地址:https://www.cnblogs.com/wyb666/p/10305134.html
Copyright © 2011-2022 走看看