文章目录
- 一、面试题
- (1)题1
- 二、常见算法题目
- (1)题1
- (2)题2
- (3)题3
- (4)题4
- (5)题5
- 三、案例
一、面试题
(1)题1
🌋题目描述
下面代码输出结果是?
🌱代码
package StringTest;/*** ClassName: StringTest* Package: StringTest* Description:* 考查:方法参数的值传递机制、String的不可变性* @Author 雨翼轻尘* @Create 2024/2/16 0016 9:47*/public class StringTest {String str = "good";char[] ch = { 't', 'e', 's', 't' };public void change(String str, char ch[]) {str = "test ok";ch[0] = 'b';}public static void main(String[] args) {StringTest ex = new StringTest();ex.change(ex.str, ex.ch);System.out.println(ex.str); //goodSystem.out.println(ex.ch); //best}
}
🍺输出
🍰分析
凡是涉及到参数传递机制,基本数据类型传递数据值,引用数据类型传递地址值。
当改变"test ok"的时候,副本是由于指向的地址发生了变化导致内容发生了变化,而原来的实参str指向的地址内容(good)没有改变,因此原来的str仍然为good。
这一点与c++中常用指针参数不同,传入指针参数时,是可以修改指向地址的内容,因此重新赋值会导致在指向地址上的内容发生变化,而Java中String不变性是改变副本的地址指向从而改变内容而不是在实参指向地址的内容上覆盖原值。
方法里面的str只是形参,没有改实参。
必须在原地址上修改它指向的内容才可以,这里的str是参数,重新赋值了,换了一个地址,不影响原来地址的数据。
二、常见算法题目
(1)题1
🌋题目描述
模拟一个trim方法,去除字符串两端的空格。
🌱代码
package StringTest;/*** ClassName: StringTest1* Package: StringTest* Description:* 题目1:模拟一个trim方法,去除字符串两端的空格。* @Author 雨翼轻尘* @Create 2024/2/16 0016 10:49*/
//题目1:
public class testMyTrim{public static void main(String[] args) {MyTrim str=new MyTrim();String str1 = " abcd ";String str2 = " ";String str3=str.myTrim1(str1);String str4 = str.myTrim1(str2);System.out.println("---" + str3 + "---"); //---abcd---System.out.println("---" + str4 + "---"); //------}
}class MyTrim {public String myTrim1(String str) {if (str != null) {int start = 0;// 用于记录从前往后首次索引位置不是空格的位置的索引int end = str.length() - 1;// 用于记录从后往前首次索引位置不是空格的位置的索引while (start < end && str.charAt(start) == ' ') {start++;}while (start < end && str.charAt(end) == ' ') {end--;}if (str.charAt(start) == ' ') {return "";}return str.substring(start, end + 1);}return null;}
}
🍺输出
🍰分析
比如此时输入了一个字符串,从前往后找到第一个没有空格的位置,将索引记一下;然后从后往前找第一个没有空格的位置,将索引记一下。
然后取当前字符串的substring
即可。
☕注意
①char charAt(index):返回[index]位置的字符。
②String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
(2)题2
🌋题目描述
将一个字符串进行反转。将字符串中指定部分进行反转。比如“ab**cdef**
g”反转为”ab**fedc**
g”。
🍰分析
【方法一】
将String
转为char
型数组,针对于char型数组进行相应位置的反转,反转之后再将char型数组转为String。
【方法二】
将要变换的字符串分为三部分,先输出前面的一部分,中间的一部分倒着输出,然后拼接上最后的一部分。
🌱代码1
package StringTest;/*** ClassName: StringTest2* Package: StringTest* Description:* 题目2:将一个字符串进行反转。将字符串中指定部分进行反转。* 比如"abcdefg"反转为"abfedcg"* @Author 雨翼轻尘* @Create 2024/2/16 0016 11:06*/
public class StringTest2 {public static void main(String[] args) {ReverseTest test=new ReverseTest();String s="abcdefg";String s1 = test.reverse(s, 2, 5);//索引号从0开始,比如[2,5]System.out.println(s1); //"abfedcg"}
}/*
* 方法一、将String转为char型数组,针对于char型数组进行相应位置的反转,反转之后再将char型数组转为String
*/class ReverseTest{public String reverse(String str,int fromIndex,int toIndex){//1.将String转化为char[]char[] arr = str.toCharArray();//2.让char[]数组某一段反转for (int i = fromIndex,j=toIndex; i <j ; i++,j--) {char temp=arr[i];arr[i]=arr[j];arr[j]=temp;}//3.将char[]返回Stringreturn new String(arr);}
}
🍺输出1
🌱代码2
package StringTest;/*** ClassName: StringTest2* Package: StringTest* Description:* 题目2:将一个字符串进行反转。将字符串中指定部分进行反转。* 比如"abcdefg"反转为"abfedcg"* @Author 雨翼轻尘* @Create 2024/2/16 0016 11:06*/
public class StringTest2 {public static void main(String[] args) {ReverseTest test=new ReverseTest();String s="abcdefg";String s1 = test.reverse(s, 2, 5);//索引号从0开始,比如[2,5]System.out.println(s1); //"abfedcg"}/*
* 方法二、将要变换的字符串分为三部分,先输出前面的一部分,中间的一部分倒着输出,然后拼接上最后的一部分
*/class ReverseTest{public String reverse(String str,int fromIndex,int toIndex){//1.获取str的第1部分String finalStr=str.substring(0,fromIndex); //[0,fromIndex) --> ab//2.拼接上第2部分for (int i = toIndex; i >= fromIndex; i--) { //从后往前倒着来finalStr+=str.charAt(i); //取出指定位置的字符,拼接到第1部分后面} //循环结束 --> abfedc//3.拼接上第3部分finalStr+=str.substring(toIndex+1);return finalStr;}}
🍺输出2
☕注意
- public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
- String 类的构造器:String(char[]) 和 String(char[],int offset,int length) 分别用字符数组中的全部字符和部分字符创建字符串对象。
- String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
- String substring(int beginIndex) :返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- char charAt(index):返回[index]位置的字符。
🎲方式一和方式二哪个性能更好?
方式一更好。
方式二中finalStr+=str.substring(toIndex+1);
操作,每次+=
的时候,+前后有变量参与,都是new一个新的字符串,这里拼接了四次,那么就需要创建四次空间,有点浪费。速度也比较慢。
方式一中直接拿char型数组在交换,没有新内存的开辟。在原有数据上操作,速度也会更快一些。
(3)题3
🌋题目描述
获取一个字符串在另一个字符串中出现的次数。
比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数。
🌱代码
package StringTest;/*** ClassName: StringTest3* Package: StringTest* Description:* 题目3:获取一个字符串在另一个字符串中出现的次数。* 比如:获取"ab"在 "abkkcadkabkebfkabkskab" 中出现的次数* @Author 雨翼轻尘* @Create 2024/3/27 0027 9:19*/public class StringTest3 {public static void main(String[] args) {getSubString test=new getSubString();String subStr="ab";String str="abkkcadkabkebfkabkskab";int count=test.getSubStringCount(str,subStr);System.out.println(count);}
}class getSubString{/*** 判断字符串subStr在str中出现的次数* @param str* @param subStr 子字符串* @return 返回次数*/public int getSubStringCount(String str,String subStr){int count=0; //记录ab出现的次数if(str.length()>=subStr.length()){int index=str.indexOf(subStr); //返回字符串subStr在str中第一次出现的索引while(index>=0){ //如果index大于等于0,则让count++count++;index=str.indexOf(subStr,index+subStr.length());}}return count;}
}
🍺输出
🍰分析
通过观察,"ab"出现了4次。
我们可以写一个方法,用count来记录出现的次数。如下:
public class StringTest3 {/*** 判断字符串subStr在str中出现的次数* @param str* @param subStr 子字符串* @return 返回次数*/public int getSubStringCount(String str,String subStr){ int count=0; //记录ab出现的次数return count;}
}
这里使用indexOf
来寻找字符串subStr第一次出现的索引。
public int getSubStringCount(String str,String subStr){int count=0; //记录ab出现的次数int index=str.indexOf(subStr); //返回字符串subStr在str中第一次出现的索引if(index>=0){ //如果index大于等于0,则让count++count++;}return count;
}
这里使用if不太合适,因为不会只找一次,还需要接着判断,所以改用while。
从哪里开始找?从上一个找到的字符串后面开始继续找。
刚才已经在index位置找到了,这里不能写index:
具体看图:
所以应该这样写:str.indexOf(subStr,index+subStr.length());
比如获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数,第一次找到“ab”返回索引index是0,然后应该从“0+ab长度”的位置开始继续找,即从索引为2的位置(k)继续找。
若是找到了,就返回索引index,然后判断index是大于等于0的,继续循环,让count++,直到没有找到然后返回index为-1,循环结束。
如下:
public class StringTest3 {/*** 判断字符串subStr在str中出现的次数* @param str* @param subStr 子字符串* @return 返回次数*/public int getSubStringCount(String str,String subStr){int count=0; //记录ab出现的次数int index=str.indexOf(subStr); //返回字符串subStr在str中第一次出现的索引while(index>=0){ //如果index大于等于0,则让count++count++;index=str.indexOf(subStr,index+subStr.length());}return count;}
}
接下来做一个测试:
public class StringTest3 {/*** 判断字符串subStr在str中出现的次数* @param str* @param subStr 子字符串* @return 返回次数*/public int getSubStringCount(String str,String subStr){int count=0; //记录ab出现的次数int index=str.indexOf(subStr); //返回字符串subStr在str中第一次出现的索引while(index>=0){ //如果index大于等于0,则让count++count++;index=str.indexOf(subStr,index+subStr.length());}return count;}@Testpublic void test2(){String subStr="ab";String str="abkkcadkabkebfkabkskab";int count=getSubStringCount(str,subStr);System.out.println(count);}
}
输出:
这里还可以提前做一个判断,str的长度需要大于等于子串subStr的长度:(若不是,则直接返回count的值0)
☕注意
- int indexOf(xx):从前往后找当前字符串中xx,如果有则返回第一次出现的下标,要是没有就返回-1。
- int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
(4)题4
🌋题目描述
获取两个字符串中最大相同子串。
比如:
str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm”
提示:将短的那个串进行长度依次递减的子串与较长的串比较。
🌱代码
package StringTest;/*** ClassName: StringTest4* Package: StringTest* Description:* 题目4:获取两个字符串中最大相同子串。比如:* str1 = "abcwerthelloyuiodef";* str2 = "cvhellobnm"* 提示:将短的那个串进行长度依次递减的子串与较长的串比较。* @Author 雨翼轻尘* @Create 2024/3/27 0027 10:51*/import org.junit.Test;import java.util.Arrays;public class StringTest4 {//题目4// 如果只存在一个最大长度的相同子串public String getMaxSameSubString(String str1, String str2) {if (str1 != null && str2 != null) {String maxStr = (str1.length() > str2.length()) ? str1 : str2;String minStr = (str1.length() > str2.length()) ? str2 : str1;int len = minStr.length();for (int i = 0; i < len; i++) {// 0 1 2 3 4 此层循环决定要去几个字符for (int x = 0, y = len - i; y <= len; x++, y++) {if (maxStr.contains(minStr.substring(x, y))) {return minStr.substring(x, y);}}}}return null;}// 如果存在多个长度相同的最大相同子串// 此时先返回String[],后面可以用集合中的ArrayList替换,较方便public String[] getMaxSameSubString1(String str1, String str2) {if (str1 != null && str2 != null) {StringBuffer sBuffer = new StringBuffer();String maxString = (str1.length() > str2.length()) ? str1 : str2;String minString = (str1.length() > str2.length()) ? str2 : str1;int len = minString.length();for (int i = 0; i < len; i++) {for (int x = 0, y = len - i; y <= len; x++, y++) {String subString = minString.substring(x, y);if (maxString.contains(subString)) {sBuffer.append(subString + ",");}}System.out.println(sBuffer);if (sBuffer.length() != 0) {break;}}String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,");return split;}return null;}// 如果存在多个长度相同的最大相同子串:使用ArrayList (第12章集合章节中讲ArrayList)// public List<String> getMaxSameSubString1(String str1, String str2) {// if (str1 != null && str2 != null) {// List<String> list = new ArrayList<String>();// String maxString = (str1.length() > str2.length()) ? str1 : str2;// String minString = (str1.length() > str2.length()) ? str2 : str1;//// int len = minString.length();// for (int i = 0; i < len; i++) {// for (int x = 0, y = len - i; y <= len; x++, y++) {// String subString = minString.substring(x, y);// if (maxString.contains(subString)) {// list.add(subString);// }// }// if (list.size() != 0) {// break;// }// }// return list;// }//// return null;// }@Testpublic void testGetMaxSameSubString() {String str1 = "abcwerthelloyuiodef";String str2 = "cvhellobnmiodef";String[] strs = getMaxSameSubString1(str1, str2);System.out.println(Arrays.toString(strs));}}
🍺输出
🍰分析
两个地位平等的字符串,找最大相同子串。
先找到比较短的那个字符串,然后看看是否在长的字符串中存在(contains);若没有,那么就在短的字符串中截一段(subString),再次在长的字符串中寻找。一直到返回值为true,就是要找的那个字符串。
①全部
②砍最后一个字母
③砍最后两个字母
④砍最后三个字母
以此类推。
(5)题5
🌋题目描述
对字符串中字符进行自然顺序排序。
提示:
1)字符串变成字符数组。
2)对数组排序,选择,冒泡,Arrays.sort();
3)将排序后的数组变成字符串。
🌱代码
package StringTest;import org.junit.Test;import java.util.Arrays;/*** ClassName: StringTest5* Package: StringTest* Description:* 题目5:对字符串中字符进行自然顺序排序。* 提示:* 1)字符串变成字符数组。* 2)对数组排序,选择,冒泡,Arrays.sort();* 3)将排序后的数组变成字符串。* @Author 雨翼轻尘* @Create 2024/3/27 0027 10:54*/
public class StringTest5 {//题目5@Testpublic void testSort() {String str = "abcwerthelloyuiodef";char[] arr = str.toCharArray();Arrays.sort(arr);String newStr = new String(arr);System.out.println(newStr);}
}
🍺输出
三、案例
🌋题目描述
案例:模拟用户登录
(1)定义用户类,属性为用户名和密码,提供相关的getter和setter方法,构造器,toString()。
(2)使用数组存储多个用户对象。
(3)录入用户和密码,对比用户信息,匹配成功登录成功,否则登录失败。
- 登录失败时,当用户名错误,提示没有该用户。
- 登录失败时,当密码错误时,提示密码有误。
效果如图所示:
🌱代码
【User.java】
package StringTest2;/*** ClassName: User* Package: StringTest2* Description:* 定义用户类,属性为用户名和密码,提供相关的getter和setter方法,构造器,toString()。* @Author 雨翼轻尘* @Create 2024/3/28 0028 19:12*/
public class User {private String name; //用户名private String password; //密码public User() {}public User(String name, String password) {this.name = name;this.password = password;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getpassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return name+"-"+password;}
}
【UserTest.java】
package StringTest2;import java.util.Scanner;/*** ClassName: UserTest* Package: StringTest2* Description:** @Author 雨翼轻尘* @Create 2024/3/28 0028 19:16*/
public class UserTest {public static void main(String[] args) {//1.创建数组并初始化几个User对象User[] arr=new User[3];arr[0]=new User("Tom","7777");arr[1]=new User("Jeck","8888");arr[2]=new User("Jerry","9999");System.out.println("库中的用户有:");for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]); //调用toString方法}//2.实例化Scanner,获取输入的用户名和密码Scanner scan=new Scanner(System.in);System.out.print("请输入用户名: ");String userName=scan.next();System.out.println("请输入密码");String password=scan.next();//3.遍历数组元素,匹配用户名和密码boolean isFlag=true;for (int i = 0; i < arr.length; i++) {if(arr[i].getName().equals(userName) ){ //存在此用户名isFlag=false; //找到用户名就改一下值if(arr[i].getpassword().equals(password)){System.out.println("登录成功:"+userName);}else{System.out.println("密码错误");}break;}}if(isFlag){System.out.println("没有该用户");}scan.close();}
}
🍺输出
①登录成功
②密码错误
③没有该用户