String类浅谈
分析阶段
1.首先这个类主要功能是干嘛?
答:主要是对于字符串的操作,比如字符串长度,比较,替换,截取,等等操作
2.这个类有哪些特点?
答:final关键字,不可变,字符串常量池
final关键字
1.被final修饰的变量是相当于常量,不可变,而且需要初始化
修饰基本数据类型,value不可变,修饰引用数据类型,地址不可变。
2.被final修饰的方法,方法不能被重写
3.被final修饰的类,类不能被继承
面试题(浅层)
1.String、Stringbuilder、stringbuffer有什么区别?
答:这个在我们频繁需要操作字符串的时候我们一般不使用string对象,因为他会频繁在堆创建新的String对象,产生很多垃圾。每次修改字符串,他们都会创建新的的对象然后将地址指向这个新的对象地址。再就是我们如果在多线程的时候尽量不使用stringbuilder来创建对象,虽然他创建的对象我们可以在对象本身的基础上进行操作,但是在多线程的情况下,他是不安全的,当我们多个线程在使用该对象时,可能会同时拿到同一个count的值,最后我们与运行的结果会发生偏差。前面我们说完string 和stringbuilder,再就是我们stringbuffer了,他我感觉是两则的一个过度,适用于单线程线程安全并且需要经常操作字符串的时候,而且运行效率比stringbuilder好一点
2.string中有哪些常用的方法?
字符串比较的方法:compareTo():大于则返回大于0的内容,小于则相反,等于则为0 字符串查找的方法: contains() indexOf() 字符串拆分 split() 字符串截取 substring(int beginIndex) substring(int beginIndex, int endIndex) 另外: ●public String strim() // 去掉字符串中的左右空格,保留中间空格 ●public String toUpperCase() // 字符串转大写 ●publci String toLowerCase() // 字符串转小写 ●public String intern() // 字符串入对象池 ●public String concat(String str) // 字符串连接,等同于“+” ●public int length() // 取得字符串长度 ●public boolean isEmpty() // 判断是否为空字符串(但不是null,而是长度为0)
3.string对象为什么不可变
答:string之所以不可变我大概知道四个点
第一点我们value对象被我们final关键字修饰,也就是说我们不能够修改变量的引用。
第二点就是在string中,属性都是私有的,没有暴露给外界
第三点就是这个类被final修饰,表示这个类不能被继承,因为我们经常有使用父类引用指向子类实现的方式,会破坏string的不可变
第三点则是string中的方法都没设置主动修改value的值,需要改动的话都是新建一个新的string对象
string为啥被涉及成不可变?
答:我们string对象经常被使用,所以我们需要再空间,安全,性能上去充分设计。
涉及到具体的方法使用
4.如何检查字符串中只包含数字?
public static void main(String[] args) { digitsOnlyString("wen狗"); digitsOnlyString("1239"); } /** * 使用正则表达式进行判断是否只包含数字 * * @param string 输入的字符串 */ private static void digitsOnlyString(String string) { if (string.matches("\\d+")) { System.out.println("只包含数字的字符串:" + string); } else { System.out.println("此字符包含其他字符:" + string); } }
5.如何从字符串中找出第一个不重复的字符?
public static void main(String[] args) { System.out.println(printFirstNonRepeatingChar("jaasjoon小蜗牛")); } /** * @param string 输入的字符串 * @return 返回结果字符 */ private static Character printFirstNonRepeatingChar(String string) { // 将字符串转换成字符数组 char[] chars = string.toCharArray(); // 声明一个字符list List<Character> characterList = new ArrayList<>(); // 外层循环遍历chars数组 for (int i = 0; i < chars.length; i++) { char c = chars[i]; // 如果characterList中已存在字符c则结束当前循环 if (characterList.contains(c)) { continue; } // 从字符c的下一个字符开始遍历,如果后面的字符有与字符c相同的则加入到characterList中,结束这个循环 // 如果从字符c的下一个字符开始直到最后一个字符都没有与此字符相同的,则此字符即为第一个不重复的字符 for (int j = i + 1; j < chars.length; j++) { if (c == chars[j]) { characterList.add(c); break; } else if (j == chars.length - 1) { return c; } } } return null; }
6.如何在不用第三个变量的情况下交换两个字符串?
public static void main(String[] args) { String s1 = "wen"; String s2 = "小狗"; s1 = s1.concat(s2); s2 = s1.substring(0, s1.length() - s2.length()); s1 = s1.substring(s2.length()); System.out.println("s1=" + s1); System.out.println("s2=" + s2); }
7.如何判断一个字符串包含了另外一个字符串?
public static void main(String[] args) { String s1 = "wen"; String s2 = "w"; System.out.println(s1.contains(s2)); } // contains方法源码 public boolean contains(CharSequence s) { return indexOf(s.toString()) > -1; }
8.如何统计字符串中的单词数?
public static void main(String[] args) { countNumberOfWords("My name is java"); } /** * 实现思路: * 1、去掉首尾空格, * 2、然后采用split方法,使用正则表达式, * 3、split的结果是数组,这个数组的长度就是单词个数 * * @param line 输入的一行句子 */ private static void countNumberOfWords(String line) { String trimmedLine = line.trim(); int count = trimmedLine.isEmpty() ? 0 : trimmedLine.split("\\s+").length; System.out.println(count); }
9.如何删除所有出现的指定字符?
public static void main(String[] args) { removeCharFromString("wenfd", 'n'); } /** * 实现思路: * String类没有提供remove操作,但是提供了replaceAll方法 * 因此只需要将出现的字符替换为空白即可 * * @param input 输入的字符串 * @param c 需要删除的指定字符 */ private static void removeCharFromString(String input, char c) { String result = input.replaceAll(String.valueOf(c), ""); System.out.println(result); }
10.如何判断一个字符串是前后对称的?
public static void main(String[] args) { checkPalindromeString("wen"); checkPalindromeString("wenfdsf wennosaj"); } /** * 实现思路: * 1、将字符串从中间分成两部分 * 2、进行判断第一个与最后一个,第二与倒数第二个是否相同,如果不同立马break * * 需要注意如下三点: * 1、for 循环的下标从 0 开始,到 length/2 结束 * 2、下标 i 和 length-i-1 是对称的 * 3、一旦 false 就 break * * @param input 输入的字符 */ private static void checkPalindromeString(String input) { boolean result = true; int length = input.length(); for (int i = 0; i < length / 2; i++) { if (input.charAt(i) != input.charAt(length - i - 1)) { result = false; break; } } System.out.println(input + " 对称吗? " + result); }
11.如何反转字符串?
答: 使用StringBuilder的reverse()即可
public static void main(String[] args) { reveseChar("wen"); } /** * 实现思路: * 使用StringBuilder的reverse()即可 * * @param input 输入的字符串 */ private static void reveseChar(String input) { StringBuilder stringBuilder = new StringBuilder(); String str = stringBuilder.append(input).reverse().toString(); System.out.println(str); }
12.如何在字符串中获取不同的字符及其数量?
答:
-
实现思路:
-
1、将输入的字符串转换成字符数组
-
2、遍历这个字符数组,将这个字符放入map中,并用字符作为key,字符出现的次数作为value
-
3、如果key不存在则说明出现的次数为1,此后将这个字符的原来的value加上1即可。
public static void main(String[] args) { printDistinctCharsWithCount("wen"); printDistinctCharsWithCountByLambda("wen蜗牛"); } /** * 实现思路: * 1、将输入的字符串转换成字符数组 * 2、遍历这个字符数组,将这个字符放入map中,并用字符作为key,字符出现的次数作为value * 3、如果key不存在则说明出现的次数为1,此后将这个字符的原来的value加上1即可。 * * @param input 输入的字符串 */ private static void printDistinctCharsWithCount(String input) { Map<Character, Integer> charsWithCountMap = new LinkedHashMap<>(); for (char c : input.toCharArray()) { Integer oldValue = charsWithCountMap.get(c); int newValue = (oldValue == null) ? 1 : Integer.sum(oldValue, 1); charsWithCountMap.put(c, newValue); } System.out.println(charsWithCountMap); } // 采用lambda实现 private static void printDistinctCharsWithCountByLambda(String input) { Map<Character, Integer> charsWithCountMap = new LinkedHashMap<>(); for (char c : input.toCharArray()) { charsWithCountMap.merge(c, 1, Integer::sum); } System.out.println("采用lambda实现:" + charsWithCountMap); } // merge()方法是java 8出现的新特性,第一个参数为key,第二个参数为value,第三个参数为一个BiFunction函数式接口类型, // 它的特点是把判断和计算整合成为了一步操作。 // 含义是如果key不存在则将key和value put到map中,如果key存在,则根据BiFunction计算的结果,重新覆盖原来的value值。