1.不可变类型的问题
问题:
BigInteger i = 1;
BigInteger j = 1;
i.add(j);后i是多少?1
分析:
(1)不可变类型种类:String、BigDecimal、BigInteger和各种包装器类型都是不可变类型。
(2)对于String不可变的特性在我另一篇博文中说到。
(3)比如BigInteger的add方法,并不会改变两个操作数即现有实例,而是返回新的实例。
结论:
在调用不可变对象的方法时,如果对于看起来是对对象进行改变的方法,则现有实例并不会改变,而是返回一个新的实例。
import java.math.*; public class PuzzleDemo56{ public static void main(String args[]){ BigInteger five = new BigInteger("5"); BigInteger six = new BigInteger("6"); BigInteger total = BigInteger.ZERO; total = five.add(six); System.out.println("5 + 6 = "+total); } }2.HashSet中覆写hashCode的重要性
在HashSet中寻找某个对象需要两个步骤:
(1)通过计算hashCode方法计算散列码,并对应到某个数组索引。
(2)通过数组索引对应的链表遍历,调用equals方法查找是否已经存在这个对象。
结论:
因此在HashSet中hashCode和equals方法缺一不可,当然在一般的类中,如果覆写了equals方法,就必须覆写hashCode方法。
import java.util.*; public class PuzzleDemo57{ private final String first,last; public PuzzleDemo57(String first,String last){ this.first = first; this.last = last; } @Override public boolean equals(Object o){ if(!(o instanceof PuzzleDemo57)) return false; PuzzleDemo57 n = (PuzzleDemo57)o; return n.first.equals(first) && n.last.equals(last); } @Override public int hashCode(){ return 13 * first.hashCode() + 27 * last.hashCode(); } public static void main(String args[]){ Set<PuzzleDemo57>s = new HashSet<PuzzleDemo57>(); s.add(new PuzzleDemo57("xia","zdong")); System.out.println(s.contains(new PuzzleDemo57("xia","zdong"))); } }
3.八进制表示问题
问题:int i[] = {012,123,234};中 i[1]-i[0]结果是什么?113
分析:
(1)八进制表示:以0开头的整形字面常量。
结论:
千万不要在一个整型字面常量前加一个0.
import java.util.*; public class PuzzleDemo59{ public static void main(String args[]){ int vals[] = {789,678,567,456,345,234,123,12}; Set<Integer>diffs = new HashSet<Integer>(); for(int i=0;i<vals.length;i++){ for(int j=i;j<vals.length;j++){ int tmp = vals[i] - vals[j]; diffs.add(tmp); System.out.println(tmp); } } } }4.打印数组的巧妙方法
问题:如果编写一个方法打印数组,接收一个数组,但却不知道数组的维度,该怎么办?库方法
分析:
在Arrays类中有一个deepToString()方法,如果传递的是数组,则将打印数组中的内容。
结论:
要了解类库中的方法。
import java.util.*; public class PuzzleDemo60{ public static void main(String args[]){ String[]strs = {"spam","sausage","spam","bacon","spam"}; List<String> list = Arrays.asList(strs); List<String> list2 = deleteMore(list); System.out.println(list2); int[][]s = new int[3][2]; s[0][0] = 1; s[0][1] = 1; s[1][0] = 1; s[1][1] = 1; s[2][0] = 1; s[2][1] = 1; System.out.println(Arrays.deepToString (s)); } public static List<String> deleteMore (List<String> list){ return new ArrayList<String>(new LinkedHashSet<String>(list)); } }5.如果要在List中去除重复元素,则可以把他放到Set中,则会自动去除。
6.Integer.bitCount(int i)返回i变成二进制后被置位的位数。
7.Date和Calendar的一些规定
(1)在这两个类中,月份都是从0开始计数,即一月是0。
(2)Date的方法基本都已经过时,所以不要使用。
(3)Calendar cal = Calendar.getInstance();创建一个实例。
(4)cal.set(int year,int mon,int day);设置时间。
import java.util.*; public class PuzzleDemo61{ public static void main(String args[]){ Calendar cal = Calendar.getInstance(); cal.set(1999,Calendar.DECEMBER,31); System.out.print(cal.get(Calendar.YEAR)+" "); System.out.println(cal.get(Calendar.DAY_OF_MONTH)); } }8.Math.abs(i)一定返回非负数?
问题:Math.abs(Integer.MIN_VALUE)返回什么?Integer.MIN_VALUE.
分析:
(1)一般情况下,返回的是非负数。
(2)当参数为Integer.MIN_VALUE时,则返回是其本身。
import java.util.*; public class PuzzleDemo64{ public static void main(String args[]){ int min = Math.abs(Integer.MIN_VALUE); System.out.println(min); //打印的仍是Integer.MIN_VALUE. final int MODULUS = 3; int[] histogram = new int[MODULUS]; int i = Integer.MIN_VALUE; do{ histogram[mod(i,MODULUS)]++; }while(i++!=Integer.MAX_VALUE); for(int j=0;j<MODULUS;j++){ System.out.println(histogram[j]+" "); } } public static int mod(int i,int modulus){ int result = i%modulus; return result<0?result+modulus: result; } }9.惯用法比较器真的正确?
问题:
Comparator comp = new Comparator<Integer>(){ public int compare(Integer i,Integer j){ return i-j; } } |
这种传统的比较器真的正确吗?不!
分析:
(1)这种惯用法是不合理的,因为i-j可能会溢出。
结论:
Comparator<Integer> comp = new Comparator<Integer>(){ public int compare(Integer i,Integer j){ return i<j?-1:((i==j)?0:1); } }; |
这种比较器是没有问题的。
因此千万不要使用基于减法的比较器。