我尝试在Java中实现Incognito k-anonymization algorithm。 该算法的一部分是给定表的频率集构造。表的列每次都有所不同,所以我决定将表表示为Object []的ArrayList,其中Object [] size是列的数量。在此对象中,我存储每列的每一行的值。
我尝试使用以下方法构建频率表:
ArrayList<Object[]> table = new ArrayList<Object[]>();
....// table filling//.....
ArrayList<Object[]> frequencySet = new ArrayList<Object[]>();
for(int i=0;i<table.size();i++)
{
Integer count = 1;
int j = 0;
for(j=i+1;j<table.size();j++)
{
if(Arrays.equals(table.get(i), table.get(j)))
{
//System.out.println(i+" equals to "+j);
count++;
table.remove(j);
j = j-1;
}
}
int size = arguments.size()+1;
Object[] anObject = new Object[size];
System.arraycopy(table.get(i), 0, anObject, 0, arguments.size());
anObject[size-1] = count;
frequencySet.add(anObject);
}
问题是算法非常慢,我发现在这种方法中大部分时间都消耗了。 (对于100.000数据,它需要13分钟才能运行 - 我不知道这是否正常)。有没有更快的方法来构建频率表?
答案 0 :(得分:3)
永远不要在remove
上使用ArrayList
,它是O(size())。此外,每次递增时,count计数变量都会被包装和解包。设置其类型int
并仅在最后将其包装到Integer
。
在不知道您存储的对象类型的情况下,我假设为它们重新定义了方法equals
和hashCode
。然后想到的最好的事情是将Object的数组包装到一个Row类中(无论如何都要做好事),重新定义equals和hashCode for Row(使用Arrays.equals和Arrays.hashCode)并计算每个的出现次数。使用
HashMap<Row, Integer> count;
进行一次传递
for (Row row : table) {
if (count.containsKey(row)) {
count.put(row, count.get(row) + 1);
} else {
count.put(row, 1);
}
}
答案 1 :(得分:1)
对它们进行排序,然后用循环计算重复次数。这将把它降低到O(n log n)
或使用散列表来进行计数。那应该是线性时间计算。