JDK原始碼閱讀-CharSequence介面

七印miss發表於2019-01-13

概述

java.lang.CharSequence介面是一個可讀的字元序列。此介面為不同型別的字元序列提供了一種統一且只讀的訪問方式。如String、StringBuilder、CharArray等都實現了該介面。
CharSequence介面沒refine Object類中定義的equals和hashCode方法的通用約定,因此對於兩個實現了該介面的物件而言,在進行對比是,通常其結果也是未定義的。同時,使用任意的CharSequence例項作為set集合的元素或者map中的key是不合適的,因為實現該介面的每個物件可以由不同的類來實現,導致無法保證每個類都有和其他類例項有等價的測試能力。

宣告方式

java不可以直接new一個抽象型別或者介面的物件,但是可以直接為其賦予合法的值,如:CharSequence cs = "charSequence";

方法

CharSequence介面方法
從上圖,我們可以看到經常在字串中使用的length(),charAt(int)等方法。

length()方法

返回字元序列的長度。由於String類採用的是UTF-16編碼,因此該方法返回的值肯定是16bit的整數倍。

int length(); // 介面的方法預設由public修飾
複製程式碼

charAt(int)方法

  • 返回指定索引index位置處的字元。
  • 如果指定索引位置處的字元值為surrogate字元,則返回這個surrogate字元。(surrogate的出現原因:因為UTF-16採用2個位元組儲存一個字元,但是有的字元儲存只需要一個位元組,比如英文字元,那麼下一個位元組也不能繼續儲存其他的字元,而只能儲存一個代表字元,來佔用這一個位元組的位置,接下來的一個位元組處才能繼續儲存下一個字元)。
char charAt(int index);
複製程式碼

subSequence(int, int)方法

返回一個由原字元序列擷取的子序列。子序列包含原序列的第start個位置的字元,但不含第end個位置的字元。另外,如果入參start==end,則返回空序列。

CharSequence subSequence(int start, int end);
複製程式碼

toString()方法

染回字元序列的字串形式。

public String toString();
複製程式碼

chars()方法

這個方法是在jdk1.8新加的,先佔個坑,之後再分析。

    public default IntStream chars() {
        class CharIterator implements PrimitiveIterator.OfInt {
            int cur = 0;

            public boolean hasNext() {
                return cur < length();
            }

            public int nextInt() {
                if (hasNext()) {
                    return charAt(cur++);
                } else {
                    throw new NoSuchElementException();
                }
            }

            @Override
            public void forEachRemaining(IntConsumer block) {
                for (; cur < length(); cur++) {
                    block.accept(charAt(cur));
                }
            }
        }

        return StreamSupport.intStream(() ->
                Spliterators.spliterator(
                        new CharIterator(),
                        length(),
                        Spliterator.ORDERED),
                Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED,
                false);
    }
複製程式碼

codePoints()方法

這個方法是在jdk1.8新加的,先佔個坑,之後再分析。

public default IntStream codePoints() {
        class CodePointIterator implements PrimitiveIterator.OfInt {
            int cur = 0;

            @Override
            public void forEachRemaining(IntConsumer block) {
                final int length = length();
                int i = cur;
                try {
                    while (i < length) {
                        char c1 = charAt(i++);
                        if (!Character.isHighSurrogate(c1) || i >= length) {
                            block.accept(c1);
                        } else {
                            char c2 = charAt(i);
                            if (Character.isLowSurrogate(c2)) {
                                i++;
                                block.accept(Character.toCodePoint(c1, c2));
                            } else {
                                block.accept(c1);
                            }
                        }
                    }
                } finally {
                    cur = i;
                }
            }

            public boolean hasNext() {
                return cur < length();
            }

            public int nextInt() {
                final int length = length();

                if (cur >= length) {
                    throw new NoSuchElementException();
                }
                char c1 = charAt(cur++);
                if (Character.isHighSurrogate(c1) && cur < length) {
                    char c2 = charAt(cur);
                    if (Character.isLowSurrogate(c2)) {
                        cur++;
                        return Character.toCodePoint(c1, c2);
                    }
                }
                return c1;
            }
        }

        return StreamSupport.intStream(() ->
                Spliterators.spliteratorUnknownSize(
                        new CodePointIterator(),
                        Spliterator.ORDERED),
                Spliterator.ORDERED,
                false);
    }
複製程式碼

與String類的異同

String是CharSequence介面的一個實現,也就是說String也是CharSequence型別。

System.out.println(
    new String("string") instanceof CharSequence); // true
複製程式碼

相關文章