【java学习】String字符串

1,概念

1)String 不可变

①创建过程

String s = "Google";
System.out.println("s = " + s);

s = "Runoob";
System.out.println("s = " + s);

这里写图片描述
在实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = “Runoob”; 创建了一个新的对象 “Runoob”,而原来的 “Google” 还存在于内存中。
②地址比较
在内存中,相同的字符串只存在一个实例,所以地址相同;但char[]地址不同。
只要对字符串改变,就会产生新的实例。

public void test() {
        String str1 = "hello world";
        String str2 = "hello world";
        if (str1 == str2)
            System.out.println("str1 == str2");
        else
            System.out.println("str1 != str2");
        char[] str3 = "hello world".toCharArray();
        char[] str4 = "hello world".toCharArray();

        if (str3 == str4)
            System.out.println("str3 == str4");
        else
            System.out.println("str3 != str4");
    }

结果:

str1 == str2
str3 != str4

2)空串

含有一个或多个空格字符的串称为空串

3)形参传递

引用类型作为形参传递会改变实参的值,但是String是特殊的引用类型,作为形参传递不会影响实参的值。

2,数据结构-串

1)概念

字符位置:字符在序列中的序号(从1开始)
子串位置:第一个字符在主串的位置。

2)串的模式匹配:KMP算法(克努特—莫里斯—普拉特操作)

①概念

串的模式匹配:子串的定位操作通常称做模式匹配,是各种串处理系统中最重要的操作之一。
KMP算法:给定两个字符串O和f,长度分别为n和 m,判断f是否在O中出现,如果出现则返回出现的位置。常规方法是遍历O的每一个位置,然后从该位置开始和f进行匹配,但是这种方法的复杂度是 O(nm)。kmp算法通过一个O(m)的预处理,使匹配的复杂度降为O(n+m)。

②KMP算法核心

每次匹配失败就隔N-X个字符进行下一次匹配(因为N的大小是N,没有N个字符是不可能匹配成功的)(X指的是在上一段字符中能匹配成功的字符数)

③复杂度分析

最好情况:每趟匹配不成功都是在第一个字符,即每趟都只需匹配一次就知道该趟是否匹配。O(m+n)
最坏情况:每趟匹配不成功都是在最后一个字符。时间复杂度O(m*n)

④计算

计算前缀 Next[i] 的值:
我们令 next[0] = -1 。从 next[1] 开始,每求一个字符的 next 值,就看它前面是否有一个最长的”字符串”和从第一个字符开始的”字符串”相等(需要注意的是,这2个”字符串”不能是同一个”字符串”)。如果一个都没有,这个字符的 next 值就是0;如果有,就看它有多长,这个字符的 next 值就是它的长度。

计算修正后的 Nextval[i] 值:
我们令 nextval[0] = -1。
从 nextval[1] 开始,如果某位(字符)与它 next 值指向的位(字符)相同,则该位的 nextval 值就是指向位的 nextval 值(nextval[i] = nextval[ next[i] ]);
如果不同,则该位的 nextval 值就是它自己的 next 值(nextvalue[i] = next[i])。

举例:
这里写图片描述
计算前缀 Next[i] 的值:(next数组里面就是最长重复子串字符串的个数)
next[0] = -1;定值。
next[1] = 0;s[1]前面没有重复子串。
next[2] = 0;s[2]前面没有重复子串。
next[3] = 0;s[3]前面没有重复子串。
next[4] = 1;s[4]前面有重复子串s[0] = ‘a’和s[3] = ‘a’。
next[5] = 2;s[5]前面有重复子串s[01] = ‘ab’和s[34] = ‘ab’。
next[6] = 3;s[6]前面有重复子串s[012] = ‘abc’和s[345] = ‘abc’。
next[7] = 4;s[7]前面有重复子串s[0123] = ‘abca’和s[3456] = ‘abca’。

计算修正后的 Nextval[i] 值:
nextval[0] = -1;定值。
nextval[1] = 0; ( s[1] = b ) != ( s[ next[1] ] = s[0] = a ),nextval[1] = next[1] = 0。
nextval[2] = 0; ( s[2] = c ) != ( s[ next[2] ] = s[0] = a ),nextval[2] = next[2] = 0。
nextval[3] = -1; ( s[3] = a ) == ( s[ next[3] ] = s[0] = a ),nextval[3] = nextval[ next[3] ] = nextval[0] = -1。
nextval[4] = 0; ( s[4] = b ) == ( s[ next[4] ] = s[1] = b ),nextval[4] = nextval[ next[4] ] = nextval[1] = 0。
nextval[5] = 0; ( s[5] = c ) == ( s[ next[5] ] = s[2] = c ),nextval[5] = nextval[ next[5] ] = nextval[2] = 0。
nextval[6] = -1; ( s[6] = a ) == ( s[ next[6] ] = s[3] = a ),nextval[6] = nextval[3] = -1。
nextval[7] = 4; s[7] != s[4],nextval[7] = next[7] = 4。

注意:下标可以从1开始,那么nextval各位加1,应该为:0,1,1,0,1,1,0,5

再举个例子感受下next的计算:

i        0  1  2  3  4  5  6  7  8
s        a  b  a  b  a  a  b  a  b
next    -1  0  0  1  2  3  1  2  3 
nextval -1  0 -1  0 -1  3  0 -1  0

3,字符串函数

1)转换

①String 2 char[]

char[] ch = str.toCharArray();

②String 2 String[]

将分隔符分开的字符串转换为数组

data = "aa_bb_cc";
String[] param = data.split("_");

param={“aa”,”bb”,”cc”}

③字符数组转为字符串

String.valueOf(ch);

④String2Uri

Uri uri = Uri.parse("skdfjlk");

⑤int2String

int i = 1;  
String.valueOf(i);//方法一  
Integer.toString(i);//方法二  
String iStr = i+"";//方法三  

⑥String2Date2Long

String timeStr = "12:09";//12分09秒  
SimpleDateFormat sdf1 = new SimpleDateFormat("hh:mm");  
long nMin = 1000*60;//一分钟的毫秒数  
Date timeDate = sdf.parse(timeNowStr);//获得日期格式  
long time = timeDate.getTime()/nMin;//获得分钟数  

⑦String2int

        String s = "10";  
        int i1 = Integer.valueOf(s);//方法一  
        int i2 = Integer.parseInt(s)+1;//方法二  

2) Java String API

1   char charAt(int index)
返回指定索引处的 char 值。
2   int compareTo(Object o)
把这个字符串和另一个对象比较。
o -- 可以是一个 Byte, Double, Integer, Float, Long 或 Short 类型的参数。
如果指定的数与参数相等返回0。
如果指定的数小于参数返回 -1。
如果指定的数大于参数返回 13   int compareTo(String anotherString)
按字典顺序比较两个字符串。
4   int compareToIgnoreCase(String str)
按字典顺序比较两个字符串,不考虑大小写。
5   String concat(String str)
将指定字符串连接到此字符串的结尾。(也可以使用+,它可以连接任何数据)
6   boolean contentEquals(StringBuffer sb)
当且仅当字符串与指定的StringButter有相同顺序的字符时候返回真。
7   static String copyValueOf(char[] data)
返回指定数组中表示该字符序列的 String。
8   static String copyValueOf(char[] data, int offset, int count)
返回指定数组中表示该字符序列的 String。
9   boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。
10  boolean equals(Object anObject)
将此字符串与指定的对象比较。
11  boolean equalsIgnoreCase(String anotherString)
将此 String 与另一个 String 比较,不考虑大小写。
12  byte[] getBytes()
 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
13  byte[] getBytes(String charsetName)
使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
14  void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
将字符从此字符串复制到目标字符数组。
15  int hashCode()
返回此字符串的哈希码。
16  int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引。
17  int indexOf(int ch, int fromIndex)
返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
18  int indexOf(String str)
 返回指定子字符串在此字符串中第一次出现处的索引。
19  int indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
str1.IndexOf("字"); //查找“字”在str1中的索引值(位置)
str1.IndexOf("字串");//查找“字串”的第一个字符在str1中的索引值(位置)
str1.IndexOf("字",start,end);//从str1第start+1个字符起,查找end个字符,查找“字”在字符串STR1中的位置[从第一个字符算起]注意:start+end不能大于str1的长度
20  String intern()
 返回字符串对象的规范化表示形式。
21  int lastIndexOf(int ch)
 返回指定字符在此字符串中最后一次出现处的索引。
22  int lastIndexOf(int ch, int fromIndex)
返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
23  int lastIndexOf(String str)
返回指定子字符串在此字符串中最右边出现处的索引。
24  int lastIndexOf(String str, int fromIndex)
 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
25  int length()
返回此字符串的长度。
26  boolean matches(String regex)
告知此字符串是否匹配给定的正则表达式。
27  boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
28  boolean regionMatches(int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
29  String replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
30  String replaceAll(String regex, String replacement
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
31  String replaceFirst(String regex, String replacement)
 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
32  String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串。
33  String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。
将“abc*ad*ac”换为“abc”,“ad”,"ac"
String[] str_split = new String[3];
str_split = str.split("\\*")
34  boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。
35  boolean startsWith(String prefix, int toffset)
测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
36  CharSequence subSequence(int beginIndex, int endIndex)
 返回一个新的字符序列,它是此序列的一个子序列。
37  String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。
38  String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。
str.substring(3);//"Hello world!"-->"lo world!"
str.substring(3,7);//"Hello world!"-->"lo w"
str = str.substring(0,str.length()-1) 去掉最后一位
39  char[] toCharArray()
将此字符串转换为一个新的字符数组。
40  String toLowerCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
41  String toLowerCase(Locale locale)
 使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。
42  String toString()
 返回此对象本身(它已经是一个字符串!)。
43  String toUpperCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
44  String toUpperCase(Locale locale)
使用给定 Locale 的规则将此 String 中的所有字符都转换为大写。
45  String trim()
返回字符串的副本,忽略前导空白和尾部空白。
46  static String valueOf(primitive data type x)
返回给定data type类型x参数的字符串表示形式。

3)格式化字符串

①对整数进行格式化:%[index$][标识][最小宽度]转换方式

格式化字符串由4部分组成:
a.特殊的格式:以%index$开头,index从1开始取值,表示将第index个参数拿进来进行格式化
b标识:

 '-' 在最小宽度内左对齐,不可以与"用0填充"同时使用
 '#' 只适用于8进制和16进制,8进制时在结果前面增加一个016进制时在结果前面增加0x
 '+' 结果总是包括一个符号(一般情况下只适用于10进制,若对象为BigInteger才可以用于8进制和16进制)
 ' ' 正值前加空格,负值前加负号(一般情况下只适用于10进制,若对象为BigInteger才可以用于8进制和16进制)
 '0' 结果将用零来填充
 ',' 只适用于10进制,每3位数字之间用","分隔
 '(' 若参数是负数,则结果中不添加负号而是用圆括号把数字括起来(同'+'具有同样的限制)
转换方式:

c.[最小宽度]:最终该整数转化的字符串最少包含多少位数字。
d.转换方式:

d-十进制 o-八进制 x或X-十六进制

举例:

System.out.println(String.format("%1$,09d", -3123));//-0003,123
System.out.println(String.format("%1$9d", -31));//      -31
System.out.println(String.format("%1$-9d", -31));//-31
System.out.println(String.format("%1$(9d", -31));// (31)

②对浮点数进行格式化:%[index$][标识][最少宽度][.精度]转换方式

转换方式:

'e', 'E' -- 结果被格式化为用计算机科学记数法表示的十进制数
'f' -- 结果被格式化为十进制普通表示方式
'g', 'G' -- 根据具体情况,自动选择用普通表示方式还是科学计数法方式
'a', 'A' -- 结果被格式化为带有效位数和指数的十六进制浮点数

③对字符进行格式化:

对字符进行格式化是非常简单的,c表示字符,标识中’-‘表示左对齐,其他就没什么了。

4,String、StringBuffer和StringBuilder区别

1)String

字符串常量。
是不可变对象。每次对String对象改变时,都等同生成了一个新的String对象,然后指针指向新的String对象,从而耗内存,影响系统性能。
在一下字符串对象生成中,String效率远比StringBuffer快:

 String S1 = “This is only a” + “ simple” + “ test”;
 StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

但如果拼接的字符串来自另外的String对象,速度就会变慢,如:

String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;

2)StringBuffer

①概念

区别于不可变对象String,StringBuffer和StringBuilder底层是char[]数组实现的,是可变长度的。
字符串变量(线程安全),类似String字符串缓冲区。
推荐使用。每次修改对象的值都是修改对象本身,不生成新的对象。减少GC,提高效率。

②容量

StringBuffer默认初始大小为16;
StringBuffer扩容:

s = new StringBuffer(x);
s.append(y);
1.当y<x时,capacity值为x;
以下情况,容器容量需要扩展:
2.当x<y<2*x+2时,值为 2*x+2
3.当y>2*x+2时,值为y

StringBuffer和StringBuilder的默认大小为16
ArrayList和LinkedList的默认大小10

③方法

append方法:追加字符串。
insert方法:在指定点添加字符。z.insert(4, "le")//“start”-->“starlet”
length: 返回当前长度
capacity:返回初始化的长度

3)StringBuilder

字符串变量(非线程安全).
比StringBuffer快,但不保证同步,多用在单线程(推荐)。

5,Character类

1)概念

Character 类用于对单个字符进行操作。
Character 类在对象中包装一个基本类型 char 的值

// 字符数组
char[] charArray ={ 'a', 'b', 'c', 'd', 'e' };

Character ch = new Character('a');

// 原始字符 'a' 装箱到 Character 对象 ch 中
Character ch = 'a';
// 返回拆箱的值到 'c',原始字符 'x' 用 test 方法装箱
char c = test('x');

2) java.lang.Character API

Character 方法:

1   isLetter()
是否是一个字母
2   isDigit()
是否是一个数字字符
3   isWhitespace()
是否是一个空格
4   isUpperCase()
是否是大写字母
5   isLowerCase()
是否是小写字母
6   toUpperCase()
指定字母的大写形式
7   toLowerCase()
指定字母的小写形式
8   toString()
返回字符的字符串形式,字符串的长度仅为1

6,其他应用

1)判断字符串是否为数字

public class TypeJudgeUtil {  

    /** 
     * 判断字符串是否是数字 
     * @param s 
     * @return 
     */  
    public static boolean isNum(String s){  

        boolean result = false;  

        if ( null == s || s.equals("")) {  
            result = false;  
        }  
        else {  
            try {  
                Integer.parseInt(s);  
                result = true;  
            } catch (Exception e) {  
                result = false;  
            }  
        }  
        return result;  
    }  
}  

2)SpannableString

①设置分段字的颜色

 SpannableStringBuilder builder=new SpannableStringBuilder("");
        builder.setSpan(new ForegroundColorSpan(Color.RED),0,1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

②设置分段字的大小

//分段设置字的大小(第一个字号为12sp,第二个字号为13sp)
SpannableStringBuilder builder = new SpannableStringBuilder("¥" + str);
builder.setSpan(new AbsoluteSizeSpan(ChangeView.dip2px(context, 12)), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new AbsoluteSizeSpan(ChangeView.dip2px(context, 13)), 2, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_price.setText(builder);

③设置分段点击事件

SpannableString spanableInfo = new SpannableString("温馨提示:为注册订易点账号的手机号,登录是将自动注册,且代表您已同意" + "《用户服务协议》");
spanableInfo.setSpan(new Clickable(clickListener), 34, 42, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

④文字中添加图片

drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM); 
SpannableString spannableString = new SpannableString(" "); 
spannableString.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

3)字符串智能截取

package luo.StringCut;
/**
 * 字符串截取函数
 * 要求:
 * 1,输入一个字符串和字节数,输出为按字节截取的字符串。
 * 2,保证汉字不被截半个,例如("人ABC",4)="人AB",("人ABC们EF",6)="人ABC"
 * @author luo
 *
 *分析:
 *java语言中,默认使用Unicode编码方式,即每个字符占两个字节,
 *因此可以用来存储中文。
 *虽然String是由char组成,但存储时,每个英文占一个字符,中文2个字符。
 */
public class StringCut {

    /**
     * 判断字符c是否是中文字符,如果是返回true
     * @return
     */
    private static boolean isChinese(char c){
        String s = String.valueOf(c);
        return s.getBytes().length>1 ? true : false;
    }
    public static String StringCut(String str, int len){
        if(null == str || 0 == len){
            return "";
        }
        if(str.length() < len){
            System.out.println("非法信息:截取长度大于字符串长度!");
            return "";
        }
        char[] charArr = str.toCharArray();
        StringBuilder sb = new StringBuilder("");
        int count = 0;//用来记录当前截取字符的长度
        for(char cc:charArr){
            if(count < len){
                if(isChinese(cc)){
                    //如果要截取子串的长度只差一个字符,但是接下来的字符是中文,则截取结果子串中不保存这个中文字符
                    if(count + 1 == len){
                        return sb.toString();
                    }
                    count = count + 2;
                    sb = sb.append(cc);
                }else{
                    count = count + 1;
                    sb = sb.append(cc);
                }
            }else{
                break;
            }
        }
        return sb.toString();
    }
}
package luo.StringCut;

public class Main {

    public static void main(String[] args){
        //("人ABC",4)="人AB",("人ABC们EF",6)="人ABC"
        System.out.println(StringCut.StringCut("人ABC",4));
        System.out.println(StringCut.StringCut("人ABC们EF",6));
    }
}

4)字符串翻转

不利用java类库,实现字符串翻转

package luo.StringReverse;
/**
 * 不利用java类库,实现字符串翻转
 * @author luo
 *
 *分析:很多种方法可以实现。
 *1,数组翻转法:
 *将字符串转换为字符数组,然后对数组进行翻转,然后再翻转为字符串。
 *2,逆序遍历法:
 *把字符串转换为字符数组,逆向遍历数组,然后拼接遍历到的字符即可。
 *3,递归法:(高水平代码)
 *递归地把字符移动到字符串的最后一个位置。
 */
public class StringReverse {

    /**
     * 1,数组翻转法:
     *将字符串转换为字符数组,然后对数组进行翻转,然后再翻转为字符串。
     */
    public static String reverse1(String str){
        char[] ch = str.toCharArray();
        char c;//交换中间值
        int len = ch.length;
        for (int i = 0; i < len/2; i++) {
            c = ch[i];
            ch[i] = ch[len - i - 1];
            ch[len - i - 1] = c;
        }
        return String.valueOf(ch);
    }

    /**
     *2,逆序遍历法:
     *把字符串转换为字符数组,逆向遍历数组,然后拼接遍历到的字符即可。
     */
    public static String reverse2(String str){
        StringBuilder sb = new StringBuilder();
        char[] ch = str.toCharArray();
        for (int i = ch.length-1; i >=0; i--) {
            sb.append(ch[i]);
        }
        return sb.toString();
    }

    /**
     *3,递归法:
     *递归地把字符移动到字符串的最后一个位置。
     */
    public static String reverse3(String str){

        if(str.length() < 1){
            return str;
        }
        return reverse3(str.substring(1)) + str.charAt(0);
    }
    /**
    *使用栈
    *①将字符串转换为char数组
    *②将char数组中的字符依次压入栈中
    *③将栈中的字符依次弹出赋值给char数组
    */
    public static String strReverseWithStack(String string){
        if(string==null||string.length()==0)return string;
        Stack<Character> stringStack = new Stack<>();
        char [] array = string.toCharArray();
        for(Character c:array){
            stringStack.push(c);
        }
        int length = string.length();
        for(int i= 0;i<length;i++){
            array[i] = stringStack.pop();
        }
        return new String(array);
    }

另一种写法,利用StringBuffer:

String src = "ABCDEF ";
String dst = new StringBuffer(src).reverse().toString();

5)把一个字符串转换成整数

java源码:

/* @param      s   the {@code String} containing the integer
     *                  representation to be parsed
     * @param      radix   the radix to be used while parsing {@code s}.表示字符串需要当做什么进制的字符串去解析
     * @return     the integer represented by the string argument in the
     *             specified radix.
     * @exception  NumberFormatException if the {@code String}
     *             does not contain a parsable {@code int}.
     */
    public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        /*
         * WARNING: This method may be invoked early during VM initialization
         * before IntegerCache is initialized. Care must be taken to not use
         * the valueOf method.
         */

        if (s == null) {
            throw new NumberFormatException("null");
        }

        //如果是空字符串,或者进制低于能解析的最小进制(2)或者高于能解析的最大进制(36),则抛出异常;
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }

        int result = 0;
        boolean negative = false;//是否是负数
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;

        if (len > 0) {
            char firstChar = s.charAt(0);
            //根据第一个字符去判断字符串代表的数字是正的还是负的,通过flag negative标记
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+')
                    throw NumberFormatException.forInputString(s);

                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            //取出字符串中的每一位字符,按照进制radix转化为数字,倘若不是数字,则返回值为-1,抛出异常。
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }

                //Java中整数值都是32位的,它是有范围的。我们需要验证字符串转化之后是不是在这个范围以内,即[Integer.MIN_VALUE, Integer.MAX_VALUE]。这里并不存在统一设置上限的写法,因为-Integer.MIN_VALUE > Integer.MAX_VALUE!
                if (result < multmin) {//确保result * radix不会超出界限
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {//判断最终是否超出界限
                    throw NumberFormatException.forInputString(s);
                }

                result -= digit;//最后返回的时候,值如果是负数直接返回,否则返回-result
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }

6)替换空格

请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
解题思路:

①从后往前打

复杂度为O(n)的解法:首先计算原字符串长度,空格个数;然后计算替换之后的长度;从字符串后面开始替换:设置两个指针分别指向原、新字符串的尾部,逐个赋值;

public void replaceSpace(char[] str) {
        if (str.length <= 0)
            return;

        int original_length = str.length;
        int number_of_space = 0;
        for (int i = 0; i < str.length; i++) {
            if (str[i] == ' ')
                ++number_of_space;
            ++i;
        }

        if (number_of_space <= 0)
            return;

        int new_length = original_length + 2 * number_of_space;

        char[] new_str = new char[new_length];
        while (original_length > 0 && new_length >= original_length) {
            if (str[original_length - 1] == ' ') {
                new_str[new_length-- - 1] = '0';
                new_str[new_length-- - 1] = '2';
                new_str[new_length-- - 1] = '%';
            } else {
                new_str[new_length-- - 1] = str[original_length - 1];
            }
            --original_length;
        }
        System.out.print(new_str);
    }

②用StringBuilder、StringBuffer类

public String replaceSpace(StringBuffer str) {
        if (str == null)
            return null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            if (String.valueOf(str.charAt(i)).equals(" ")) {
                sb.append("%20");
            } else {
                sb.append(str.charAt(i));
            }
        }
        return String.valueOf(sb);
    }

7)大数运算

一般用字符串或数组表达大数。

①打印1到最大的n位数

思路:
n可能是大数。所以要用string。打印的时候,也要注意过滤掉String中前几位无用的000.
如果在数字前面补0,我们会发现n位所有十进制其实就是n各从0到9的全排列。
全排列的递归很容易表达,数字的每一位都可能是0~9中的一个数,然后设置下一位。递归结束条件:我们已经设置了数字的最后一位。

    public void printToMaxOfNDigits(int n) {
        int[] array=new int[n];
        if(n <= 0)
            return;
        printArray(array, 0);
    }
    private void printArray(int[] array,int n) {
        for(int i = 0; i < 10; i++) {
            if(n != array.length) {
                array[n] = i;
                printArray(array, n+1);
            } else {
                boolean isFirstNo0 = false;
                for(int j = 0; j < array.length; j++) {
                    if(array[j] != 0) {
                        System.out.print(array[j]);
                        if(!isFirstNo0)
                            isFirstNo0 = true;
                    } else {
                        if(isFirstNo0)
                            System.out.print(array[j]);
                    }
                }
                System.out.println();
                return ;
            }
        }
    }

②一个函数,实现任意两个整数的加法。

考虑大数问题。考虑输入的数字有负数问题。

猜你喜欢

转载自blog.csdn.net/sunshinetan/article/details/70833161
今日推荐