在Java中,对巨大的矩阵X使用以下函数来打印其列不相同的元素:
// create the list of distinct values
List<Integer> values = new ArrayList<Integer>();
// X is n * m int[][] matrix
for (int j = 0, x; j < m; j++) {
values.clear();
for (int i = 0; i < n; i++) {
x = X[i][j];
if (values.contains(x)) continue;
System.out.println(x);
values.add(x);
}
}
首先,我按列(索引j)进行迭代,并按行(索引i)进行内部迭代。
对于不同的矩阵,此函数将被调用数百万次,因此应优化代码以满足性能要求。我想知道关于values数组。使用values = new ArrayList<Integer>();
还是values = null
代替它会更快values.clear()
?
效率更高的方法是使用Set而不是列表,例如HashSet实现。contains方法将在O(1)中运行,而不是在带有列表的O(n)中运行。您可以只调用add方法来保存一个调用。
至于您的特定问题,我将在每个循环处创建一个新的Set-对象创建并没有那么昂贵,可能比清除该set少(如底部的基准所确认-请参见EDIT 2中最有效的版本):
for (int j = 0, x; j < m; j++) {
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < n; i++) {
x = X[i][j];
if (!values.add(x)) continue; //value.add returns true if the element was NOT in the set before
System.out.println(x);
}
}
但是,知道哪个更快(新对象还是清除对象)的唯一方法是分析代码的那部分并检查两个版本的性能。
编辑
我运行了一个快速基准测试,清晰的版本似乎比在每个循环上创建一个集合要快一些(大约20%)。您仍然应该检查数据集/用例中哪一个更好。我的数据集的代码更快:
Set<Integer> values = new HashSet<Integer>();
for (int j = 0, x; j < m; j++) {
for (int i = 0; i < n; i++) {
x = X[i][j];
if (!values.add(x)) continue; //value.add returns true if the element was NOT in the set before
System.out.println(x);
}
values.clear();
}
编辑2
通过在每个循环中创建一组正确大小的新代码,可以获得实际上甚至更快的代码版本:
for (int j = 0, x; j < m; j++) {
Set<Integer> values = new HashSet<Integer>(n, 1); //right size from the beginning
for (int i = 0; i < n; i++) {
x = X[i][j];
if (!values.add(x)) continue; //value.add returns true if the element was NOT in the set before
System.out.println(x);
}
}
结果汇总
JVM预热+ JIT之后:
Set<Integer> values = new HashSet<Integer>(n, 1); =====> 280 ms
values.clear(); =====> 380 ms
Set<Integer> values = new HashSet<Integer>(); =====> 450 ms
问题内容: 我有一个包含以下代码段的受测试方法: 我的单元测试代码如下所示: 问题是,在运行测试时,测试代码永远不会进入for循环。我应该在什么时候指定条件才能进入for循环?目前,我已指定,但我猜它从未使用过。 问题答案: 您的问题是,在for-each循环中使用集合时,将调用其方法;而且您还没有使用该特定方法。 我强烈建议您传递一个真实的列表,而不是模拟列表,该列表中的元素只是您的模拟对象,您
我试图研究我的数据中有零值的概率,我开发了一个代码,当一列数据为零时输出另一列数据的值,这正是我所需要的。但是,对于577BY29数据流中的每一列和其他28列都要这样做是很困难的,所以我决定创建一个for循环,在我有以下内容的地方为我这样做: 您可以看到,当输出数据帧有n=29列时,代码循环正确,但对于上面指定的条件,代码循环不正确。 请帮忙,谢谢!
我对编程有点陌生,我被卡住了。假设我在一个项目中有五个不同的类:foo1、foo2、foo3、foo4和foo5,它们都做不同但相似的事情。现在假设我需要为每个对象创建一个新对象,比如:foo1 bar1=new foo1();foo2 bar2=新的foo2();foo3 bar3=新的foo3();等等当然这是可行的,但如果我能在一个for循环中实例化我需要的所有对象,或者至少把我想要创建的所
创建新的Arraylist(如第一种方法)与创建第二种方法之间的区别是什么?在创建一个时,您考虑了什么?
在我的很多代码中,我做了如下操作: 快速返回一个新数组,其中只包含我需要的已处理数据。但是,在其当前形式中,如果不返回任何内容,新数组将有一个
我当前正在将一个ArrayList转换为一个字符串,以便将其发送到一个DB,这样我就可以在另一端检索它,并稍后将其转换回一个ArrayList。 我的思路是通过执行以下操作将其转换为当前的字符串 是ArrayList,看起来如下所示: 当我查看数据库时,它看起来像这样 如何删除开头的和最后的以便在数据库上看起来像? 在另一端,我可以使用以下方法获得它: (我正在使用SQLite,这是我大学项目的一