Java Stringクラスを自分で書きます


とっくに車輪を作りたいと思っていたが、車輪を作りたくないプログラマーは良いプログラマーではないと聞いて、Apacheの多くのオープンソースプロジェクトに慣れているが、オープンソースのコードを見たことがない.最近、いくつかの売焦りの文章を読んだ後、急に慌てて、お忙しい中、せっかく暇なのに初めてJDKのソースバッグを開けました.初読:難解で分かりにくい、3千行以上のコード、全英語の注釈、いくつかの見知らぬ文法と見知らぬクラスを呼び出して中年のプログラマーを驚かせた.もう一度:輪郭を読み取り専用、このString.classは注釈がたくさん書いてあるので、コアコードは多くありませんか.三読:わあ、Stringクラスのコア変数全体にchar[]配列がありますか.
private final char value[];

すべての操作はこのvalue[]というコア変数で接続concat()を行い、subString()を切り取り、indexOf()、startWith()が存在するかどうかを判断します.ゆっくり:これを考えて、大学の时のあるよく知っている课程を思い出したようです.そう、「データ构造とアルゴリズム」です.この门はぼんやりしていて、だんだん远くなって、ゆっくりと私の世界を薄めてから、また役に立ちました.正直に言って、大学の时にただ1学期のデータの构造を学んだことがあって、C言语を说明して実现したので、この授业は私が试験を终えた时に舍てられて、それからもう使わないと思っています.しかし、今日は自分でString類を実現したいと思っています.よく思い出しなければなりません.年を取って中年のおじさんに向かっていますが、記憶力はまだあります.そこで、String類の基本的な操作方法を一度実現しました.JDKには完璧なString類があるので、自分で書いたのはMyStringと言います.データ構造のArrayListよりもこのクラスクラスを操作すればいいだけですが、Stringのコンテンツ実装は配列ですか.はい、私はあなたが言いたいことを知っています:Takl is clean、Show me the Code、直接コードに行きましょう!
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;

public class MyString implements Serializable, Comparable, CharSequence {

    private static final long serialVersionUID = -204188373852348874L;

    /**
     *   char   ,    
     */
    private final char[] value;

    /**
     *      
     */
    public MyString() {
        value = new char[0];
    }

    /**
     * @param str   String      
     */
    public MyString(String str) {
        this.value = str.toCharArray();
    }

    public MyString(char[] value) {
        this.value = value;
    }
    public MyString(byte[] bytes) {
         this.value = new char[bytes.length];
         for(int i = 0; i < bytes.length; i++) {
             this.value[i] = (char) bytes[i];
         }
    }
    public MyString(char value[], int offset, int count) {
        if(offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if(count <= 0) {
            if(count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if(offset <= value.length) {
                this.value = new char[0];
                return;
            }
        }
        if(offset > value.length-count) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        this.value = Arrays.copyOfRange(value, offset, count);
    }


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

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

    @Override
    public CharSequence subSequence(int start, int end) {
        if(start < 0) {
            throw new StringIndexOutOfBoundsException(start);
        }
        if(end > value.length) {
            throw new StringIndexOutOfBoundsException(end);
        }
        if(start > end) {
            throw new StringIndexOutOfBoundsException("start index is bigger than end index.");
        }

        MyString result = new MyString(Arrays.copyOfRange(value, start, end));
        return result;
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    public int compareTo(MyString anotherString) {
        if(this == anotherString) {
            return 0;
        }

        return 0;
    }

    @Override
    public String toString() {
        return new String(this.value);
    }

    public boolean equals(Object anObject) {
        if(this == anObject) {
            return true;
        }
        if(anObject instanceof MyString) {
            MyString anString = (MyString)anObject;
            if(anString.length() == value.length) {
                char[] v1 = anString.value;
                char[] v2 = value;
                int n = v1.length;
                while(n-- != 0) {
                    if(v1[n] != v2[n]) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

    //TODO
    public boolean contains(CharSequence s) {

        return true;
    }

    public int indexOf(int ch) {
        return indexOf(0, ch);
    }

    public int indexOf(int ch, int fromIndex){
        for(int i = 0; i < value.length; i++) {
            if(value[i] == ch) {
                return i;
            }
        }
        return -1;
    }
    public int indexOf(MyString str) {
        return indexOf(str, 0);
    }

    public int indexOf(MyString str, int fromIndex){
        char[] source = value;
        char[] target = str.value;
        for(int i = fromIndex; i < source.length; i++) {
            if(source[i] == target[0]){
                int index = i;
                int sameLen = 1;
                for(int j = 1; j < target.length && (i+j) < source.length; j++) {
                    if(target[j] != source[i+j]) {
                        break;
                    }
                    sameLen++;
                }
                if(sameLen == target.length) {
                    return index;
                }
            }
        }
        return -1;
    }

    public MyString concat(MyString str) {
        if(str.length() == 0) {
            return this;
        }
        int len = value.length;
        int otherLen = str.length();
        char[] buf = Arrays.copyOf(value, len + otherLen);  //      char[]  ,      +        ,                
        System.arraycopy(str.value, 0, buf, len, otherLen);
        return new MyString(buf);
    }

    public boolean startsWith(MyString prefix) {
        return this.startsWith(prefix, 0);
    }

    /**
     *              
     * @param   prefix    
     * @param   toffset         
     * @return  {@code true}               true; {@code false}     false.
     * @since   1. 0
     * @author SpringChang
     */

    public boolean startsWith(MyString prefix, int toffset){
        char[] target = prefix.value;
        char[] source = value;
        int sameLen = 0; //      
        for(int i = 0; i < target.length && (toffset+i) < source.length; i++) {
            if(source[toffset+i] != target[i]) {
                break;
            }
            sameLen++;
        }
        if(sameLen == target.length) {
            return true;
        }
        return false;
    }

    public MyString toLowerCase(){
        return this.toLowerCase(Locale.getDefault());
    }
    public MyString toLowerCase(Locale locale){
        if(locale == null) {
             throw new NullPointerException();
        }
        char[] newString = new char[value.length];
        for(int i = 0; i < value.length; i++) {
            if(value[i] >= 'A' && value[i] <= 'Z') {
                newString[i] = (char) (value[i] + 32);
            } else {
                newString[i] = value[i];
            }
        }

        return new MyString(newString);
    }

    public MyString toUpperCase(){
        return this.toUpperCase(Locale.getDefault());
    }
    public MyString toUpperCase(Locale locale) {
        if(locale == null) {
             throw new NullPointerException();
        }
        char[] newString = new char[value.length];
        for(int i = 0; i < value.length; i++) {
            if(value[i] >= 'a' && value[i] <= 'z') {
                newString[i] = (char) (value[i] - 32);
            } else {
                newString[i] = value[i];
            }
        }

        return new MyString(newString);     
    }

    public MyString substring(int beginIndex){
        if(beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        return beginIndex==0?this:new MyString(value, beginIndex, value.length-beginIndex);
    }
    public MyString substring(int beginIndex, int endIndex){
        if(beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if(endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        return beginIndex==0?this:new MyString(value, beginIndex, endIndex);
    }


    /**
     *            
     * @return       ,        ,           String  ,    String final    。
     */
    public char[] toCharArray() {
        //return this.value;         
        char[] charArr = new char[value.length];
        System.arraycopy(value, 0, charArr, 0, value.length);
        return charArr;
    }
}

控訴はmini版のStringクラスにすぎず、Stringの基本的な操作機能を実現することができ、Stringのすべての機能を完全に実現することはできません.このホイールを作るのはプロジェクト開発でJDKのStringクラスを置き換えるつもりはありません.ただ、他の人のホイールがどのように作られたのか知りたいだけです.私はあなたが本当に使えるのではないかと疑っています.次は2つのテストクラスのコードです.JDKが持っているStringと手書きのMyStringクラスを見て、それぞれ結果を出力しましょう.
JDKがStringを持ついくつかの方法をテストします.
public class TestJDKString {

    public static void main(String[] args) {
        String str1 = new String("Hello Java,");
        String str2 = new String("Hello Java,");
        System.out.println("str1 str2       ?" + (str1 == str2));      //           
        System.out.println("str1 str2      ?" + (str1.equals(str2))); //            

        String str3 = new String("Hello World,");
        System.out.println(str3.concat(str1)); //     
        System.out.println(str3.concat(str1).concat(str2));//       

        System.out.println(str3.startsWith("Hello")); //         Hello  
        System.out.println(str3.startsWith("Hello1")); //         Hello1  

        System.out.println(new String("      :I am a Java Programmer. I Love Java").toLowerCase()); //      
        System.out.println(new String("       :I am a Java Programmer. I Love Java").toUpperCase());//      
    }

}

出力結果:
str1 str2       ?false
str1 str2      ?true
Hello World,Hello Java,
Hello World,Hello Java,Hello Java,
true
false
      :i am a java programmer. i love java
       :I AM A JAVA PROGRAMMER. I LOVE JAVA

自分が手書きしたMyStringクラスのいくつかの方法をテストします.
public class TestMyString {

    public static void main(String[] args) {
        MyString str1 = new MyString("Hello Java,");
        MyString str2 = new MyString("Hello Java,");
        System.out.println("str1 str2       ?" + (str1 == str2));      //           
        System.out.println("str1 str2      ?" + (str1.equals(str2))); //            

        MyString str3 = new MyString("Hello World,");
        System.out.println(str3.concat(str1)); //     
        System.out.println(str3.concat(str1).concat(str2));//       

        System.out.println(str3.startsWith(new MyString("Hello"))); //         Hello  
        System.out.println(str3.startsWith(new MyString("Hello1"))); //         Hello1  


        System.out.println(new MyString("      :I am a Java Programmer. I Love Java").toLowerCase()); //      
        System.out.println(new MyString("       :I am a Java Programmer. I Love Java").toUpperCase());//      
    }

}

出力結果:
str1 str2       ?false
str1 str2      ?true
Hello World,Hello Java,
Hello World,Hello Java,Hello Java,
true
false
      :i am a java programmer. i love java
       :I AM A JAVA PROGRAMMER. I LOVE JAVA