总结一些个人字符串的心得,也方便做string类的面试题能灵活运用
关于字符串对象的一些常用套路(方法)
将数字转换成字符串:任何基本类型包装类都有toString() ,将数字转换成字符串
将字符串转成数字: 每个基本类型包装类 都有:
(注意:如果字符串格式不正确,则转换为数字不会成功,报异常)
Integer.parseInt(s)
Long.parseLong(s);
Byte.parseByte(s)
Float.parseFloat(s);
字符数组-->字符串 :String a = new String(字符数组);
字符串--> 字符数组 : str.toCharArray();
错误用法:String b = 'A'+'B' ; (编译报错)
错误用法:String c = 'a'; //不能够直接把一个字符转换成字符串
正确:String d = Character.toString('a'); //一个字符转换为字符串
拿出字符串中的某个字符 : char c = str.charAt(index); 字符串取出一个字符
字符串对象的方法:
charAt() --获取字符
toCharArray(字符串) --获取对应的字符数组
subString() --截取子字符串
split() --分隔
trim() --去掉首尾空格
toLowerCase(字符串) --大小写
toUpperCase(字符串) --大小写
(笔记:字符串对象的方法,只能整体转换大小写,很不灵活,还是得用到Character的转换大小写)
indexOf(字符串) --定位
lastIndexOf(字符串) --定位
contains(字符串) --定位
replaceAll () --替换
replaceFirst --替换
=============================
字符静态方法:
Character.isLetter('a'));//判断是否为字母
Character.isDigit('a')); //判断是否为数字
Character.isWhitespace(' ')); //是否是空白
Character.isUpperCase('a')); //是否是大写
Character.isLowerCase('a')); //是否是小写
Character.toUpperCase('a')); //转换为大写
Character.toLowerCase('A')); //转换为小写
========================================
StringBuffer的好用方法
append 追加
delete 删除
nsert 插入
reverse 反转
length 长度
capacity 容量(默认一开始就占19)
为什么StringBuffer可以变长?
答:StringBuffer和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度
本文最底部,有一个模拟StringBuffer是如何实现的过程
分割线=========
自动装箱
不需要调用构造方法,通过=符号自动把 基本类型 转换为 类类型 就叫装箱
int i = 5;
//基本类型转换成封装类型
Integer it = new Integer(i); //装箱-》实质它做了这个操作
//自动转换就叫装箱
Integer it2 = i;
自动拆箱
int i = 5;
Integer it = new Integer(i);
//封装类型转换成基本类型
int i2 = it.intValue(); // 拆箱-》实质它做了这个操作
//自动转换就叫拆箱
int i3 = it;
}
题目1
- 对byte,short,float,double进行自动拆箱和自动装箱
- byte和Integer之间能否进行自动拆箱和自动装箱
- 通过Byte获取byte的最大值
总结;
数字转字符串 : String.valueof(int)
字符串转数字:Integer.parseInt(str);
题目2
把浮点数 3.14 转换为 字符串 "3.14"
再把字符串 “3.14” 转换为 浮点数 3.14
如果字符串是 3.1a4,转换为浮点数会得到什么?
题目3
这个图是自然对数的计算方式。
借助Math的方法,把自然对数计算出来,看看经过自己计算的自然对数和Math.E的区别有多大
答案
题目4 --质数
统计找出一千万以内,一共有多少质数
质数概念: 只能被1和自己整除的数
举例:
5只能被 1和5整除,所以是质数
8可以被2整除,所以不是质数
答案
格式化输出笔记
如果不使用格式化输出,就需要进行字符串连接,如果变量比较多,拼接就会显得繁琐
使用格式化输出,就可以简洁明了
%s 表示字符串
%d 表示数字
%n 表示换行
printf和format能够达到一模一样的效果,如何通过eclipse查看java源代码 可以看到,在printf中直接调用了format
题目5
借助Scanner 读取字符串数据,然后用格式化输出下面
浙江温州最大皮革厂江南皮革厂倒闭了,王八蛋老板黄鹤吃喝嫖赌,欠下了3.5个亿,带着他的小姨子跑了!我们没有办法,拿着钱包抵工资!原价都是一百多、两百多、三百多的钱包,现在全部只卖二十块,统统只要二十块!黄鹤王八蛋,你不是人!我们辛辛苦苦给你干了大半年,你不发工资,你还我血汗钱,还我血汗钱!
笔记
java的换号符号是
假如想用printf 那么就是直接%n
补充其他常用的格式化
题目6 --Character
通过Scanner从控制台读取字符串,然后把字符串转换为字符数组
转换为字符数组后,筛选出控制台读取到的字符串中的大写字母和数字,并打印出来
package zsc.czy.number;
import java.util.Scanner;
public class TestNumber {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String str = s.nextLine();
char[] c = str.toCharArray();
for(char one :c){
if(Character.isUpperCase(one)){
System.out.println(one);
}
if(Character.isDigit(one)){
System.err.println(one);
}
}
}
}
笔记: 一般一个A类. XX() 都是意味着将本A类型转换成括号里的类型。
字符串对象有一个toCharArray(),可以直接将字符串转换为字符数组,一开始我还以为有String静态方法会提供此功能
字符数组 转成String 的方法是: String result2 = new String(字符数组);
笔记:
String.format(sentenceFormat, name,kill,title); 的好处是 它是返回一个字符串,方便控制,而用printf(sentenceFormat, name,kill,title)) 或System.out.format(sentenceFormat, name,kill,title);则是直接就打印出来的
题目7 --随机字符串
创建一个长度是5的随机字符串,随机字符有可能是数字,大写字母或者小写字母
给点提示: 数字和字符之间可以通过互相转换
方法1:
package zsc.czy.number;
import java.util.Scanner;
public class TestNumber {
public static void main(String[] args) {
char cs[] =new char[5];
char startC = '0';
char endC ='z'; //小转大,会自动强转
int start =startC;
int end = endC;
System.out.println(start); //48
System.out.println(end); //122
for(int i =0;i<cs.length;i++){
while(true){
char c= (char)((Math.random()*(end-start)+start));
//122-48=74 [0.0,1.0) 最小0*74+48 ,最大1.0*74+48=122
if (Character.isLetter(c) || Character.isDigit(c)) {
cs[i] = c;
break;
}
}
}
}
}
方法2
package zsc.czy.number;
import java.util.Scanner;
public class TestNumber {
public static void main(String[] args) {
String pool = "";
for (short i = '0'; i <= '9'; i++) {
pool += (char) i;
}
for (short i = 'a'; i <= 'z'; i++) {
pool += (char) i;
}
for (short i = 'A'; i <= 'Z'; i++) {
pool += (char) i;
}
char cs2[] = new char[5];
for (int i = 0; i < cs2.length; i++) {
int index = (int) (Math.random() * pool.length());
cs2[i] = pool.charAt(index);
}
String result2 = new String(cs2);
System.out.println(result2);
}
}
题目8-字符串数组排序
创建一个长度是8的字符串数组
使用8个长度是5的随机字符串初始化这个数组
对这个数组进行排序,按照每个字符串的首字母排序(无视大小写)
注1: 不能使用Arrays.sort() 要自己写
注2: 无视大小写,即 Axxxx 和 axxxxx 没有先后顺序
提示:排序的时候,借助冒泡法的思路比较逻辑是每个字符串的第一个字符,并且都转换为小写,从而达到无视大小写的效果
package zsc.czy.number;
import java.util.Arrays;
import java.util.Scanner;
public class TestNumber {
public static void main(String[] args) {
String []str = new String[8];
for(int i =0;i<str.length;i++){
str[i]= makeStr();
}
System.out.println("排序前"+Arrays.toString(str));
for (int j = 0; j < str.length; j++) {
for (int i = 0; i < str.length - j - 1; i++) {
char firstChar1 = str[i].charAt(0);
char firstChar2 = str[i + 1].charAt(0);
firstChar1 = Character.toLowerCase(firstChar1);
firstChar2 = Character.toLowerCase(firstChar2);
if (firstChar1 > firstChar2) {
String temp = str[i];
str[i] = str[i + 1];
str[i + 1] = temp;
}
}
}
System.out.println("排序后"+Arrays.toString(str));
}
public static String makeStr(){
String pool = "";
for (short i = '0'; i <= '9'; i++) {
pool+=(char)i;
}
for (short i = 'a'; i <= 'z'; i++) {
pool+=(char)i;
}
for (short i = 'A'; i <= 'Z'; i++) {
pool+=(char)i;
}
char cs2[] = new char[5];
for (int i = 0; i < cs2.length; i++) {
int index = (int) (Math.random()*pool.length());
cs2[i] = pool.charAt( index );
}
String result2 = new String(cs2);
return result2;
}
}
笔记:只有Character类才有判断是不是数字 是不是英文,是不是空行 是不是大小写 这些功能
Character.toLowerCase(X) 转变成小写
Character.isLowerCase(X) 判断小写
Character.isDigit(X) 数字
Character.isLetter(ch) 判断
Character.isLetterOrDigit(X) 可以判断是字母还是数字
另外,charAt 是 字符串对象里的方法 ,可以获得单个字符
题目9-穷举法破解密码
-
生成一个长度是3的随机字符串,把这个字符串作为当做密码
-
使用穷举法生成长度是3个字符串,匹配上述生成的密码
要求: 分别使用多层for循环 和 递归解决上述问题
普通方法1
package zsc.czy.number;
import java.util.Arrays;
import java.util.Scanner;
public class TestNumber {
public static void main(String[] args) {
String password = randomString(3);
System.out.println("密码是:" + password);
char[] guessPassword = new char[3];
outloop: for (short i = '0'; i <= 'z'; i++) {
for (short j = '0'; j <= 'z'; j++) {
for (short k = '0'; k <= 'z'; k++) {
if (!isLetterOrDigit(i, j, k))
continue;
guessPassword[0] = (char) i;
guessPassword[1] = (char) j;
guessPassword[2] = (char) k;
String guess = new String(guessPassword);
System.out.println("穷举出来的秘密是:" + guess);
if (guess.equals(password)) {
System.out.println("找到了,密码是" + guess);
break outloop;
}
}
}
}
}
private static boolean isLetterOrDigit(short i, short j, short k) {
return Character.isLetterOrDigit(i) && Character.isLetterOrDigit(j)
&& Character.isLetterOrDigit(k);
}
private static String randomString(int length) {
String pool = "";
for (short i = '0'; i <= '9'; i++) {
pool += (char) i;
}
for (short i = 'a'; i <= 'z'; i++) {
pool += (char) i;
}
for (short i = 'A'; i <= 'Z'; i++) {
pool += (char) i;
}
char cs[] = new char[length];
for (int i = 0; i < cs.length; i++) {
int index = (int) (Math.random() * pool.length());
cs[i] = pool.charAt(index);
}
String result = new String(cs);
return result;
}
}
方法2-递归
package zsc.czy.number;
public class Digui {
public static boolean found = false;
public static void main(String[] args) {
String password = randomString(3);
System.out.println("密码是:" + password);
char[] guessPassword = new char[password.length()];
generatePassword(guessPassword, password);
}
public static void generatePassword(char[] guessPassword, String password) {
generatePassword(guessPassword, 0, password);
}
public static void generatePassword(char[] guessPassword, int index,
String password) {
if (found)
return;
for (short i = '0'; i <= 'z'; i++) {
char c = (char) i;
if (!Character.isLetterOrDigit(c))
continue;
guessPassword[index] = c;
if (index != guessPassword.length - 1) {
generatePassword(guessPassword, index + 1, password);
} else {
String guess = new String(guessPassword);
// System.out.println("穷举出来的秘密是:" + guess);
if (guess.equals(password)) {
System.out.println("找到了,密码是" + guess);
found = true;
return;
}
}
}
}
private static String randomString(int length) {
String pool = "";
for (short i = '0'; i <= '9'; i++) {
pool += (char) i;
}
for (short i = 'a'; i <= 'z'; i++) {
pool += (char) i;
}
for (short i = 'A'; i <= 'Z'; i++) {
pool += (char) i;
}
char cs[] = new char[length];
for (int i = 0; i < cs.length; i++) {
int index = (int) (Math.random() * pool.length());
cs[i] = pool.charAt(index);
}
String result = new String(cs);
return result;
}
}
字符串对象的方法
上面这些都是字符串对象的方法
题目10--每个单词的首字母都转换为大写
给出一句英文句子: "let there be light"
得到一个新的字符串,每个单词的首字母都转换为大写
提示:这里题目说是首字母,所以还是得用到Character 来单个转换大小写,因为字符串对象只提供全部转大小写的功能
package zsc.czy.number;
import java.util.Arrays;
public class A {
public static void main(String[] args) {
String s = "let there be light";
String Words[]=s.split(" ");
System.out.println(Arrays.toString(Words));//[let, there, be, light]
for(int i =0;i<Words.length;i++){
char upperFirstWord =Character.toUpperCase(Words[i].charAt(0));
String rest = Words[0].substring(1); //拿到一组单词的除首位后的字符串
String newWord= upperFirstWord+rest ; //首位大字母和 余字符串拼接
Words[i] = newWord;
}
System.out.println(Arrays.toString(Words));//[Let, Tet, Bet, Let]
//开始将数组转回字符串
StringBuffer sb = new StringBuffer();
for(String word :Words){
sb.append(word+" ");
}
System.out.println(sb.toString());
}
}
题目11--英文绕口令
英文绕口令
peter piper picked a peck of pickled peppers
统计这段绕口令有多少个以p开头的单词
package zsc.czy.number;
public class B {
public static void main(String[] args) {
String s = "peter piper picked a peck of pickled peppers";
String words[] = s.split(" ");
int count=0;
for(int i=0;i<words.length;i++){
if(words[i].charAt(0)=='p'){
count++;
}
}
System.out.println(count);
}
}
题目11--练习-间隔大写小写模式
把 lengendary 改成间隔大写小写模式,即 LeNgEnDaRy
package zsc.czy.number;
public class E {
public static void main(String[] args) {
String s = "lengendary";
//字符串转数组
char []c = s.toCharArray();
StringBuffer sb = new StringBuffer();
for(int i = 0;i<s.length();i++){
if(i%2==0){
char UpperWord=Character.toUpperCase(c[i]);
sb.append(UpperWord);
}
if(i%2 ==1){
char lowWord = Character.toLowerCase(c[i]);
sb.append(lowWord);
}
}
System.out.println( sb.toString());
}
}
另一做法:
public class TestString {
public static void main(String[] args) {
// 把 lengendary 改成间隔大写小写模式,即 LeNgEnDaRy
String s = "lengendary";
char[] cs =s.toCharArray();
int count= 0;
for (int i = 0; i < cs.length; i++) {
if(0==i%2)
cs[i] = Character.toUpperCase(cs[i]);
}
String result = new String(cs);
System.out.printf(result);
}
}
题目12--练习-最后一个字母变大写
把 lengendary 最后一个字母变大写
package zsc.czy.number;
public class F {
public static void main(String[] args) {
String s = " lengendary";
char c[] = s.toCharArray();
c[c.length-1]= Character.toUpperCase(c[c.length-1]);
String str = new String(c);
System.out.println(str);
}
}
题目13-- -把最后一个two单词首字母大写
Nature has given us that two ears, two eyes, and but one tongue, to the end that we should hear and see more than we speak
把最后一个two单词首字母大写
package zsc.czy.number;
public class G {
public static void main(String[] args) {
String s = "Nature has given us that two ears, two eyes, and but one tongue, to the end that we should hear and see more than we speak";
int i =s.lastIndexOf("two");
System.out.println(i); //35
char c[] = s.toCharArray();
c[i] = Character.toUpperCase(c[i]);
System.out.println(c[i]); //T
String str = new String(c);
System.out.println(str);
}
}
笔记:字符串对象
startsWith //以...开始
endsWith //以...结束
题目13--比较字符串
创建一个长度是100的字符串数组
使用长度是2的随机字符填充该字符串数组
统计这个字符串数组里重复的字符串有多少种
package zsc.czy.number;
import java.util.Arrays;
public class H {
static String[] foundDuplicated = new String[100];
static int pos;
public static void main(String[] args) {
String s[] = new String[100];
for (int i = 0; i < s.length; i++) {
s[i] = radomString(2);
}
int count=0 ;
System.out.println(Arrays.toString(s));
for (String s1 : s) {
int repeat = 0;
for (String s2 : s) {
if (s1.equalsIgnoreCase(s2)) {
repeat++;
if (2 == repeat) {
// 当repeat==2的时候,就找打了一个非己的重复字符串
putIntoDuplicatedArray(s1);
break;
}
}
}
}
System.out.printf("总共有 %d种重复的字符串%n", pos);
if (pos != 0) {
System.out.println("分别是:");
for (int i = 0; i < pos; i++) {
System.out.print(foundDuplicated[i] + " ");
}
}
}
private static void putIntoDuplicatedArray(String s1) {
for (int i = 0; i < pos; i++){
if (foundDuplicated[i].equalsIgnoreCase(s1))
return;
}
foundDuplicated[pos++] = s1;
}
public static String radomString(int length) {
String pool = "";
for (int i = '0'; i <= '9'; i++) {
pool += (char) i;
}
for (int j = 'A'; j <= 'Z'; j++) {
pool += (char) j;
}
for (int k = 'a'; k <= 'z'; k++) {
pool += (char) k;
}
// int i = (int) (Math.random() * pool.length());
// int j = (int) (Math.random() * pool.length());
// char c[] = pool.toCharArray();
// String first = new String(Character.toString(c[i]));
// String second = new String(Character.toString(c[j]));
// String newStr = first + second;
char cs[] = new char[length];
for (int i = 0; i < cs.length; i++) {
int index = (int)(Math.random()*pool.length());
cs[i]=pool.charAt(index);
}
String result = new String(cs);
return result;
}
}
题目14--StringBuffer性能
String与StringBuffer的性能区别?
生成10位长度的随机字符串
然后,先使用String的+,连接10000个随机字符串,计算消耗的时间
然后,再使用StringBuffer连接1000000个随机字符串,计算消耗的时间
package zsc.czy.number;
public class J {
public static void main(String[] args) {
int total = 10000;
String s = randomString(10);
StringBuffer sb = new StringBuffer();
String str1 = "";
long start = System.currentTimeMillis();
for (int i = 0; i < total; i++) {
str1 += s;
}
long end = System.currentTimeMillis();
System.out.printf("使用字符串连接+的方式,连接%d次,耗时%d毫秒%n", total, end - start);
total *= 100;
start = System.currentTimeMillis();
for (int i = 0; i < total; i++) {
sb.append(s);
}
end = System.currentTimeMillis();
System.out.printf("使用StringBuffer的方式,连接%d次,耗时%d毫秒%n", total, end
- start);
//
// String ss[] = new String[10];
// String connectStr = null;
// long start = System.currentTimeMillis();
// for(int i =0;i<ss.length;i++){
// ss[i]=randomString(10);
// connectStr += ss[i];
// }
// long end = System.currentTimeMillis();
// System.out.println("用时:"+(end-start)); //打印用时:6
//奇怪,为何不用printf的话,打印的会是一个整数?
}
public static String randomString(int length) {
String pools = "";
for (int i = '0'; i < '9'; i++) {
pools += (char) i;
}
for (int j = 'a'; j < 'z'; j++) {
pools += (char) j;
}
for (int k = 'A'; k < 'Z'; k++) {
pools += (char) k;
}
char cs[] = new char[length];
for (int l = 0; l < cs.length; l++) {
int index = (int) (Math.random() * pools.length());
cs[l] = pools.charAt(index);
}
String newStr = new String(cs);
return newStr;
}
}
输出结果
三百倍的效率
题目15---MyStringBuffer
根据接口IStringBuffer ,自己做一个MyStringBuffer
原理
为什么StringBuffer可以变长?
和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度
比如说new StringBuffer("the"),其内部的字符数组的长度,是19,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了19,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中,看上去 数组长度就变长了 参考MyStringBuffer
length: “the”的长度 3
capacity: 分配的总空间 19
注: 19这个数量,不同的JDK数量是不一样的
======================================
自己模拟一StringBuffer
package zsc.czy.number;
public class MyStringBuffer implements IStringBuffer {
int capacity = 16;
int length = 0;
char[] value;
public MyStringBuffer() {
value = new char[capacity];
}
public MyStringBuffer(String str) {
this();
if (null == str) {
return;
}
// 如果容量比传入的字符串长度小,那么就增大2倍容量
if (capacity < str.length()) {
capacity = value.length * 2;
value = new char[capacity];
}
if (capacity >= str.length()) {
System.arraycopy(str.toCharArray(), 0, value, 0, str.length());
}
length = str.length(); // 字符数组的长度
}
@Override
public void append(String str) {
insert(length, str);
}
@Override
public void append(char c) {
append(String.valueOf(c));
}
@Override
public void insert(int pos, char b) {
}
@Override
public void insert(int pos, String b) {
// 边界条件判断
if (pos < 0)
return;
if (pos > length)
return;
if (null == b)
return;
// 扩容
while (length + b.length() > capacity) {
capacity = (int) ((length + b.length()) * 1.5f);
// 发现插入的字符串比原有的字符数组大 就重新new一个更大的出来,并复制到新的数组,然后改变引用指向
char[] newValue = new char[capacity];
System.arraycopy(value, 0, newValue, 0, length);
value = newValue;
}
// 如果原来字符数组的空间还有足够空间放得下新字符串里的字符的话
char[] cs = b.toCharArray();
// 先把已经存在的数据往后移
// 下面这句话需要理解
System.arraycopy(value, pos, value, pos + cs.length, length - pos);
// 把要插入的数据插入到指定位置
System.arraycopy(cs, 0, value, pos, cs.length);
length = length + cs.length;
}
@Override
public void delete(int start) {
}
@Override
public void delete(int start, int end) {
// 边界条件判断
if (start < 0)
return;
if (start > length)
return;
if (end < 0)
return;
if (end > length)
return;
if (start >= end)
return;
System.arraycopy(value, end, value, start, length - end);
length -= end - start;
}
@Override
public void reverse() {
// 1.
// 首尾 互换
for (int i = 0; i < length / 2; i++) {
char temp = value[i];
value[i] = value[length - i - 1];
value[i] = value[length - i - 1] = temp;
}
}
@Override
public String toString() {
char[] realValue = new char[length];
System.arraycopy(value, 0, realValue, 0, length);
return new String(realValue);
}
@Override
public int length() {
return 0;
}
public static void main(String[] args) {
MyStringBuffer sb = new MyStringBuffer("there light");
sb.reverse();
System.out.println(sb);
}
}