我有这个代码生成HashSet
并调用removeAll()
它。我做了一个类A
,它只是一个 int 的包装器,它记录了equals
被调用的次数——程序输出那个数字。
import java.util.*;
class A {
int x;
static int equalsCalls;
A(int x) {
this.x = x;
}
@Override
public int hashCode() {
return x;
}
@Override
public boolean equals(Object o) {
equalsCalls++;
if (!(o instanceof A)) return false;
return x == ((A)o).x;
}
public static void main(String[] args) {
int setSize = Integer.parseInt(args[0]);
int listSize = Integer.parseInt(args[1]);
Set<A> s = new HashSet<A>();
for (int i = 0; i < setSize; i ++)
s.add(new A(i));
List<A> l = new LinkedList<A>();
for (int i = 0; i < listSize; i++)
l.add(new A(i));
s.removeAll(l);
System.out.println(A.equalsCalls);
}
}
事实证明,removeAll
操作不是我预期的线性:
$ java A 10 10
55
$ java A 100 100
5050
$ java A 1000 1000
500500
事实上,它似乎是二次方的。为什么?
s.removeAll(l);
用修复它替换线以for (A b : l) s.remove(b);
按照我期望的方式行事:
$ java A 10 10
10
$ java A 100 100
100
$ java A 1000 1000
1000
为什么?
这是显示二次曲线的图表:
x 和 y 轴是 Java 程序的两个参数。z 轴是A.equals
调用次数。
该图是由这个Asymptote程序生成的:
import graph3;
import grid3;
import palette;
currentprojection=orthographic(0.8,1,1);
size(400,300,IgnoreAspect);
defaultrender.merge=true;
real[][] a = new real[][]{
new real[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
new real[]{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
new real[]{0,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
new real[]{0,1,2,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6},
new real[]{0,1,2,3,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10},
new real[]{0,1,2,3,4,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15},
new real[]{0,1,2,3,4,5,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21},
new real[]{0,1,2,3,4,5,6,28,28,28,28,28,28,28,28,28,28,28,28,28,28},
new real[]{0,1,2,3,4,5,6,7,36,36,36,36,36,36,36,36,36,36,36,36,36},
new real[]{0,1,2,3,4,5,6,7,8,45,45,45,45,45,45,45,45,45,45,45,45},
new real[]{0,1,2,3,4,5,6,7,8,9,55,55,55,55,55,55,55,55,55,55,55},
new real[]{0,1,2,3,4,5,6,7,8,9,10,66,66,66,66,66,66,66,66,66,66},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,78,78,78,78,78,78,78,78,78},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,91,91,91,91,91,91,91,91},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,105,105,105,105,105,105,105},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,120,120,120,120,120,120},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,136,136,136,136,136},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,153,153,153,153},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,171,171,171},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,190,190},
new real[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,210},
};
surface s=surface(a,(-1/2,-1/2),(1/2,1/2),Spline);
draw(s,mean(palette(s.map(zpart),Rainbow())),black);
//grid3(XYZgrid);
该数组a
是由这个 Haskell 程序生成的:
import System.Process
import Data.List
f :: Integer -> Integer -> IO Integer
f x y = fmap read $ readProcess "/usr/bin/java" ["A", show x, show y] ""
g :: [[Integer]] -> [String]
g xss = map (\xs -> "new real[]{" ++ intercalate "," (map show xs) ++ "},") xss
main = do
let n = 20
xs <- mapM (\x -> mapM (\y -> f x y) [0..n]) [0..n]
putStrLn $ unlines $ g xs