昨天面试碰见一个笔试题。题目要求:利用String自身的方法,将一个由正整数组成的字符串,转变为int数组后倒序输出(例如“123”输出321)。
public static void reverse(String str){
char[] chs = str.toCharArray();
for (int i = chs.length-1; i >0; i--) {
System.out.println((int) (chs[i])- (int) ('0'));
}
}
这是我现在认为最标准的答案,不知道大家有没有什么别的想法。
public final class String implements java.io.Serializable,Comparable<String>,CharSequence {
上面可以看出,String类实现了三个接口,用于序列化Serializable接口,用于比较的泛型接口Comparable<String>和CharSequence接口,对于前两个接口可能都比较熟悉,那么第三个接呢。
CharSequence接口有四个方法:
int length();返回字符数组的长度。
char charAt(int index):返回制定索引处的字符。
CharSequence subSequence(int start, int end);返回有start开始到end之前的字符所组成的字符数组。
String toString():返回该字符数组对应的String。
private final char value[];
private final int offset;
private final int count;
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
这是String类里定义私有变量,value[]就是String对应的字符数组,offset一直没搞懂,求指教啊,count就是String对应字符序列中的字符数,hash是String对应的hash码。其中value[]和coun应该是我们一般需要知道的,别的就不用了。
再来看看String中主要的方法:
String的构造方法有很多,可以分为以下几类:
1、不传任何参数,也就是构造一个空字符串;
2、传入String对象,StringBuffer对象或者StringBuilder对象。
3、传入byte数组,并且带别的参数,用于表示截取长度的int,截取开始位置的int和用于表示字符集的String;
4、传入char数组,其余参数包括截取开始位置的int,截取长度的int
5、传入int数组,所带参数与char类似。
length(),实现自CharSequence 接口,返回count也就是字符串长度。
isEmpty(),返回count==0。
charAt(int index),返回指定索引处的字符。
void getChars(char dst[], int dstBegin) :将字符串中的字符从begin位置开始copy到dst[]数组中。
public byte[] getBytes(String charsetName):获得byte数组。
public byte[] getBytes(Charset charset):返回制定charset的byte数组。
public byte[] getBytes():返回byte数组。
public boolean equals(Object anObject):覆盖object中的equals方法。
实现代码如下:比较简单
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
用于和StringBuffer进行内容比较的一个方法:
public boolean contentEquals(StringBuffer sb) {
synchronized (sb) {
return contentEquals((CharSequence) sb);
}
}
上面的方法实际调用了和CharSequence进行内容比较的方法,也就是针对每一位的字符进行对比,当然前面还有几个短路比较。
public boolean contentEquals(CharSequence cs) {
if (count != cs.length())
return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
char v1[] = value;
char v2[] = ((AbstractStringBuilder) cs).getValue();
int i = offset;
int j = 0;
int n = count;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
}
// Argument is a String
if (cs.equals(this))
return true;
// Argument is a generic CharSequence
char v1[] = value;
int i = offset;
int j = 0;
int n = count;
while (n-- != 0) {
if (v1[i++] != cs.charAt(j++))
return false;
}
return true;
}
public boolean equalsIgnoreCase(String anotherString):忽略大小写的同类比较。
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true : (anotherString != null)
&& (anotherString.count == count)
&& regionMatches(true, 0, anotherString, 0, count);
}
comparable接口的compareTo方法:
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[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
} else {
while (n-- != 0) {
char c1 = v1[i++];
char c2 = v2[j++];
if (c1 != c2) {
return c1 - c2;
}
}
}
return len1 - len2;
}
String还给我们提供了一个比较工具类:
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
该类的实现代码如下(比较简单):
private static class CaseInsensitiveComparator implements
Comparator<String>, java.io.Serializable {
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 8575799808933029326L;
public int compare(String s1, String s2) {
int n1 = s1.length(), n2 = s2.length();
for (int i1 = 0, i2 = 0; i1 < n1 && i2 < n2; i1++, i2++) {
char c1 = s1.charAt(i1);
char c2 = s2.charAt(i2);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
return c1 - c2;
}
}
}
}
return n1 - n2;
}
}
忽略大小写的同类比较:
public int compareToIgnoreCase(String str) {
return CASE_INSENSITIVE_ORDER.compare(this, str);
}
计算hashcode的方法(至于每位为什么乘以31而不是32,同求解):
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31 * h + val[off++];
}
hash = h;
}
return h;
}
提供的公共方法用于查找目标字符串中的字符串:
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount, int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first)
;
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end
&& source[j] == target[k]; j++, k++)
;
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
看看我们最常用的trim是怎么实现的:
public String trim() {
int len = count;
int st = 0;
int off = offset; /* avoid getfield opcode */
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[off + st] <= ' ')) {
st++;
}
while ((st < len) && (val[off + len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < count)) ? substring(st, len) : this;
}
笔试要用到的方法:
public char[] toCharArray() {
char result[] = new char[count];
getChars(0, count, result, 0);
return result;
}
将其他对象转换为String:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
public native String intern():当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
public boolean startsWith(String prefix, int toffset);
public boolean startsWith(String prefix) ;
public boolean endsWith(String suffix);
public int indexOf(int ch);
public int indexOf(int ch, int fromIndex);//该查找是从fromindex处往前找
public int lastIndexOf(int ch);
public int lastIndexOf(int ch, int fromIndex);
public int indexOf(String str);
public int indexOf(String str, int fromIndex);
public int lastIndexOf(String str);
public String substring(int beginIndex);
public String substring(int beginIndex, int endIndex);
public CharSequence subSequence(int beginIndex, int endIndex);
public String concat(String str);
public String replace(char oldChar, char newChar);
public boolean matches(String regex);
public boolean contains(CharSequence s);
public String replaceFirst(String regex, String replacement);
public String replaceAll(String regex, String replacement);
public String replace(CharSequence target, CharSequence replacement);
public String[] split(String regex, int limit);
public String[] split(String regex);
public static String valueOf(char data[]);
public static String copyValueOf(char data[], int offset, int count);
public static String valueOf(boolean b);
有误之处,敬请拍砖!