昨天面试碰见一个笔试题。题目要求:利用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);
有误之处,敬请拍砖!