技术小菜鸟 发表于 2013-11-22 23:02

compareTo()的内部是否有遍历的存在?

本人新手,最近在看compareTo()方法时在想compareTo()的内部也是有遍历的存在呢?可是在网上找不到这个,求高手讲讲其中的内部实现

ddd010 发表于 2013-11-28 21:43

//android的String类
/*
* public int compareTo(String s)
*/
bool javaLangString_compareTo(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
    JValue* pResult)
{
    /*
   * Null reference check on "this".Normally this is performed during
   * the setup of the virtual method call.We need to do it before
   * anything else.While we're at it, check out the other string,
   * which must also be non-null.
   */
    if ((Object*) arg0 == NULL || (Object*) arg1 == NULL) {
      dvmThrowNullPointerException(NULL);
      return false;
    }

    /* quick test for comparison with itself */
    if (arg0 == arg1) {
      pResult->i = 0;
      return true;
    }

    /*
   * This would be simpler and faster if we promoted StringObject to
   * a full representation, lining up the C structure fields with the
   * actual object fields.
   */
    int thisCount, thisOffset, compCount, compOffset;
    ArrayObject* thisArray;
    ArrayObject* compArray;
    const u2* thisChars;
    const u2* compChars;
    int minCount, countDiff;

    thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
    compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
    countDiff = thisCount - compCount;
    minCount = (countDiff < 0) ? thisCount : compCount;
    thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
    compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
    thisArray = (ArrayObject*)
      dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
    compArray = (ArrayObject*)
      dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
    thisChars = ((const u2*)(void*)thisArray->contents) + thisOffset;
    compChars = ((const u2*)(void*)compArray->contents) + compOffset;

#ifdef HAVE__MEMCMP16
    /*
   * Use assembly version, which returns the difference between the
   * characters.The annoying part here is that 0x00e9 - 0xffff != 0x00ea,
   * because the interpreter converts the characters to 32-bit integers
   * *without* sign extension before it subtracts them (which makes some
   * sense since "char" is unsigned).So what we get is the result of
   * 0x000000e9 - 0x0000ffff, which is 0xffff00ea.
   */
    int otherRes = __memcmp16(thisChars, compChars, minCount);
# ifdef CHECK_MEMCMP16
    int i;
    for (i = 0; i < minCount; i++) {
      if (thisChars != compChars) {
            pResult->i = (s4) thisChars - (s4) compChars;
            if (pResult->i != otherRes) {
                badMatch((StringObject*) arg0, (StringObject*) arg1,
                  pResult->i, otherRes, "compareTo");
            }
            return true;
      }
    }
# endif
    if (otherRes != 0) {
      pResult->i = otherRes;
      return true;
    }

#else
    /*
   * Straightforward implementation, examining 16 bits at a time.Compare
   * the characters that overlap, and if they're all the same then return
   * the difference in lengths.
   */
    int i;
    for (i = 0; i < minCount; i++) {
      if (thisChars != compChars) {
            pResult->i = (s4) thisChars - (s4) compChars;
            return true;
      }
    }
#endif

    pResult->i = countDiff;
    return true;
}

ddd010 发表于 2013-11-28 21:47

//openjdk6 的实现
    /**
   * Compares two strings lexicographically.
   * The comparison is based on the Unicode value of each character in
   * the strings. The character sequence represented by this
   * <code>String</code> object is compared lexicographically to the
   * character sequence represented by the argument string. The result is
   * a negative integer if this <code>String</code> object
   * lexicographically precedes the argument string. The result is a
   * positive integer if this <code>String</code> object lexicographically
   * follows the argument string. The result is zero if the strings
   * are equal; <code>compareTo</code> returns <code>0</code> exactly when
   * the {@link #equals(Object)} method would return <code>true</code>.
   * <p>
   * This is the definition of lexicographic ordering. If two strings are
   * different, then either they have different characters at some index
   * that is a valid index for both strings, or their lengths are different,
   * or both. If they have different characters at one or more index
   * positions, let <i>k</i> be the smallest such index; then the string
   * whose character at position <i>k</i> has the smaller value, as
   * determined by using the &lt; operator, lexicographically precedes the
   * other string. In this case, <code>compareTo</code> returns the
   * difference of the two character values at position <code>k</code> in
   * the two string -- that is, the value:
   * <blockquote><pre>
   * this.charAt(k)-anotherString.charAt(k)
   * </pre></blockquote>
   * If there is no index position at which they differ, then the shorter
   * string lexicographically precedes the longer string. In this case,
   * <code>compareTo</code> returns the difference of the lengths of the
   * strings -- that is, the value:
   * <blockquote><pre>
   * this.length()-anotherString.length()
   * </pre></blockquote>
   *
   * @param   anotherString   the <code>String</code> to be compared.
   * @returnthe value <code>0</code> if the argument string is equal to
   *          this string; a value less than <code>0</code> if this string
   *          is lexicographically less than the string argument; and a
   *          value greater than <code>0</code> if this string is
   *          lexicographically greater than the string argument.
   */
    public int compareTo(String anotherString) {
      int len1 = count;
      int len2 = anotherString.count;
      int n = Math.min(len1, len2);
      char v1[] = value;
      char v2[] = anotherString.value;
      int i = offset;
      int j = anotherString.offset;

      if (i == j) {
            int k = i;
            int lim = n + i;
            while (k < lim) {
                char c1 = v1;
                char c2 = v2;
                if (c1 != c2) {
                  return c1 - c2;
                }
                k++;
            }
      } else {
            while (n-- != 0) {
                char c1 = v1;
                char c2 = v2;
                if (c1 != c2) {
                  return c1 - c2;
                }
            }
      }
      return len1 - len2;
    }

ddd010 发表于 2013-11-28 21:47

//openjdk6 的实现
    /**
   * Compares two strings lexicographically.
   * The comparison is based on the Unicode value of each character in
   * the strings. The character sequence represented by this
   * <code>String</code> object is compared lexicographically to the
   * character sequence represented by the argument string. The result is
   * a negative integer if this <code>String</code> object
   * lexicographically precedes the argument string. The result is a
   * positive integer if this <code>String</code> object lexicographically
   * follows the argument string. The result is zero if the strings
   * are equal; <code>compareTo</code> returns <code>0</code> exactly when
   * the {@link #equals(Object)} method would return <code>true</code>.
   * <p>
   * This is the definition of lexicographic ordering. If two strings are
   * different, then either they have different characters at some index
   * that is a valid index for both strings, or their lengths are different,
   * or both. If they have different characters at one or more index
   * positions, let <i>k</i> be the smallest such index; then the string
   * whose character at position <i>k</i> has the smaller value, as
   * determined by using the &lt; operator, lexicographically precedes the
   * other string. In this case, <code>compareTo</code> returns the
   * difference of the two character values at position <code>k</code> in
   * the two string -- that is, the value:
   * <blockquote><pre>
   * this.charAt(k)-anotherString.charAt(k)
   * </pre></blockquote>
   * If there is no index position at which they differ, then the shorter
   * string lexicographically precedes the longer string. In this case,
   * <code>compareTo</code> returns the difference of the lengths of the
   * strings -- that is, the value:
   * <blockquote><pre>
   * this.length()-anotherString.length()
   * </pre></blockquote>
   *
   * @param   anotherString   the <code>String</code> to be compared.
   * @returnthe value <code>0</code> if the argument string is equal to
   *          this string; a value less than <code>0</code> if this string
   *          is lexicographically less than the string argument; and a
   *          value greater than <code>0</code> if this string is
   *          lexicographically greater than the string argument.
   */
    public int compareTo(String anotherString) {
      int len1 = count;
      int len2 = anotherString.count;
      int n = Math.min(len1, len2);
      char v1[] = value;
      char v2[] = anotherString.value;
      int i = offset;
      int j = anotherString.offset;

      if (i == j) {
            int k = i;
            int lim = n + i;
            while (k < lim) {
                char c1 = v1;
                char c2 = v2;
                if (c1 != c2) {
                  return c1 - c2;
                }
                k++;
            }
      } else {
            while (n-- != 0) {
                char c1 = v1;
                char c2 = v2;
                if (c1 != c2) {
                  return c1 - c2;
                }
            }
      }
      return len1 - len2;
    }

ddd010 发表于 2013-11-28 22:32

网络问题,发重了。版主删除掉一个。
页: [1]
查看完整版本: compareTo()的内部是否有遍历的存在?