String类之详解(二)

String类之详解(二)

5.String类中获取功能的函数

 int length()
          返回此字符串的长度。
 char charAt(int index)
          返回指定索引处的 char 值。
 int indexOf(int ch)
          返回指定字符在此字符串中第一次出现处的索引。
 int indexOf(int ch, int fromIndex)
          返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。
 int indexOf(String str)
          返回指定子字符串在此字符串中第一次出现处的索引。
 int indexOf(String str, int fromIndex)
          返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
 int lastIndexOf(int ch)
          返回指定字符在此字符串中最后一次出现处的索引。
 int lastIndexOf(int ch, int fromIndex)
          返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。
 int lastIndexOf(String str)
          返回指定子字符串在此字符串中最右边出现处的索引。
 int lastIndexOf(String str, int fromIndex)
          返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
 String substring(int beginIndex)
          返回一个新的字符串,它是此字符串的一个子字符串。
 String substring(int beginIndex, int endIndex)
          返回一个新字符串,它是此字符串的一个子字符串。

(1)length()

private final char value[];

public int length() {
        return value.length;
    }

注:Java中length、length()、size()的区别:

1.length不是方法,是属性,数组的长度属性;

实际上,数组的 length 属性是 Java 编译器在编译时给加上的,为其分配了 1 个字长的内存空间,用于存储数组的长度。这个 length 属性相当于数组对象中一个 public final static int length = ?; 的属性。

对于该属性,我没有在任何一个类中的源码中找到,查找资料后还是一知半解,详情见(https://bbs.csdn.net/topics/110121291),如有收获可以讨论。上条为感觉比较靠谱的说法。

2.length()是字符串String的一个方法,底层实现如上,即为返回属性length;

3.size()方法,是集合的一个方法,底层ArrayList中实现如下,即为返回属性length;

        private final E[] a;

        public int size() {
            return a.length;
        }

(2)charAt(int index)

public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

此处会抛出 StringIndexOutOfBoundsException异常,相当于数据越界异常。

(3)indexOf(int ch)    indexOf(int ch,int fromIndex)

public int indexOf(int ch) {
        return indexOf(ch, 0);
    }
//UTF-16 编码中的 Unicode 高代理项代码单元的最小值/最大值
public static final char MIN_HIGH_SURROGATE = '\uD800';
public static final char MAX_HIGH_SURROGATE = '\uDBFF';

public int indexOf(int ch, int fromIndex) {
        final int max = value.length;        //获取字符串长度
        if (fromIndex < 0) {                 //如果起始位置 < 0,则从0开始
            fromIndex = 0;
        } else if (fromIndex >= max) {       //如果起始位置 > 字符串长度,则返回-1
            // Note: fromIndex might be near -1>>>1.
            return -1;
        }

        //如果ch小于最小值
        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // 逐个比较,找到返回下标,未找到返回-1
            final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return indexOfSupplementary(ch, fromIndex);
        }
    }
private int indexOfSupplementary(int ch, int fromIndex) {
        if (Character.isValidCodePoint(ch)) {
            final char[] value = this.value;
            final char hi = Character.highSurrogate(ch);
            final char lo = Character.lowSurrogate(ch);
            final int max = value.length - 1;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == hi && value[i + 1] == lo) {
                    return i;
                }
            }
        }
        return -1;
    }
public static boolean isValidCodePoint(int codePoint) {
        // Optimized form of:
        //     codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
        int plane = codePoint >>> 16;
        return plane < ((MAX_CODE_POINT + 1) >>> 16);
    }

public static char highSurrogate(int codePoint) {
        return (char) ((codePoint >>> 10)
            + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
    }

public static char lowSurrogate(int codePoint) {
        return (char) ((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
    }

好难,,,,看不懂,,,,希望有大神讲解。。。。(此处之后的博客会补充)

对于indexOf(String str)与indexOf(String str,int fromIndex)源码分析见上一篇文章(https://mp.csdn.net/postedit/83658987

对于lastIndexOf源码原理与上述基本相同,可自行阅读

(4)substring(int beginIndex)    substring(int beginIndex, int endIndex)

String substring(int beginIndex) {
        if (beginIndex < 0) {        //如果起始偏移量小于0,抛出异常
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {            //如果起始偏移量大于字符串长度,抛出异常
            throw new StringIndexOutOfBoundsException(subLen);
        }                    
        //如果起始偏移量 = 0 ,则返回本字符串
        //否则,创建新字符串,从偏移量处到末尾
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

//参数为字符数组,起始偏移量,长度
public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {        //长度小于0,抛出异常。长度=0,创建空字符串。
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        //起始偏移量 + 截取长度 > 字符串长度
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        //调用函数
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
static char[] copyOfRange(char[] original, int from, int to)
          将指定数组的指定范围复制到一个新数组。
/**
*@param original 原数组
*@param from 起始偏移量
*@param to 终止偏移量
*/
public static char[] copyOfRange(char[] original, int from, int to) {
        int newLength = to - from;
        if (newLength < 0)        //终止偏移量小于起始偏移量,抛出异常
            throw new IllegalArgumentException(from + " > " + to);
        char[] copy = new char[newLength];
        //调用函数
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }
public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

 调用系统方法,关于native的介绍请见(https://mp.csdn.net/postedit/83622837

substring(int beginIndex, int endIndex)的底层源码与上述基本相同,可自行阅读。

由此可见,substring方法返回的是一个新字符串,并没有对原有字符串进行修改,所以如果需要应用,注意赋值操作。

6.获取功能函数的应用

(1)遍历字符串

        String s = "java";	
        //通过for循环获取到字符串中每个字符的索引
	for(int i = 0; i < s.length(); i++) {			
		System.out.println(s.charAt(i));		//通过索引获取每一个字符	
	}

(2)统计字符串中字符类型

        String s = "ABCDEabcd123456!@#$%^";
	int big = 0;
	int small = 0;
	int num = 0;
	int other = 0;
	//1,获取每一个字符,通过for循环遍历
	for(int i = 0; i < s.length(); i++) {
		char c = s.charAt(i);	
		//2,判断字符是否在这个范围内
		if(c >= 'A' && c <= 'Z') {
			big++;									
		}else if(c >= 'a' && c <= 'z') {
			small++;
		}else if(c >= '0' && c <= '9') {
			num++;
		}else {
			other++;
		}
	}		
	//3,打印每一个计数器的结果
	System.out.println(s + "中大写字母有:" + big + "个,小写字母有:" + small + "个,数字字符:" 
		+ num + "个,其他字符:" + other + "个");

猜你喜欢

转载自blog.csdn.net/qq_40298054/article/details/83691967