GVKun编程网logo

在for循环中重新创建ArrayList的最快方法(for循环重新循环)

14

这篇文章主要围绕在for循环中重新创建ArrayList的最快方法和for循环重新循环展开,旨在为您提供一份详细的参考资料。我们将全面介绍在for循环中重新创建ArrayList的最快方法的优缺点,解

这篇文章主要围绕在for循环中重新创建ArrayList的最快方法for循环重新循环展开,旨在为您提供一份详细的参考资料。我们将全面介绍在for循环中重新创建ArrayList的最快方法的优缺点,解答for循环重新循环的相关问题,同时也会为您带来Array.fill和for循环创建Array有什么区别、ArrayList list = new ArrayList()在这个泛型为Integer的ArrayList中存放一个String类型的对象、ArrayList在for循环中使用remove方法移除元素方法介绍、c – 在for循环中重新排序测试条件:编译器错误?的实用方法。

本文目录一览:

在for循环中重新创建ArrayList的最快方法(for循环重新循环)

在for循环中重新创建ArrayList的最快方法(for循环重新循环)

在Java中,对巨大的矩阵X使用以下函数来打印其列不相同的元素:

// create the list of distinct valuesList<Integer> values = new ArrayList<Integer>();// X is n * m int[][] matrixfor (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 = newArrayList<Integer>();还是values = null代替它会更快values.clear()

答案1

小编典典

效率更高的方法是使用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 msvalues.clear();                                   =====> 380 msSet<Integer> values = new HashSet<Integer>();     =====> 450 ms

Array.fill和for循环创建Array有什么区别

Array.fill和for循环创建Array有什么区别

我正在使用React.js创建一个地牢爬虫游戏,并且正在使用Array.fill(0)来初始化棋盘。但是当我在2d数组内设置元素时,它将整个Array(列)设置为,'player'而不是单个元素。我有另一个createBoard()功能,注释掉,可以正常工作。那么,为什么会发生这种情况?如何正确使用Array.fill?

这是我的董事会组件:

import React,{Component} from 'react';
import Cell from './Cell';

class Board extends Component {
  constructor(props) {
    super(props);
    const dim = 10;
    let board = this.createBoard(dim,dim);
    this.state = {
      board: board,};
  }

  createBoard = (row,col) => {
    return Array(row).fill(Array(col).fill(0));
  }

  // createBoard = (rows,cols) => {
  //   let board = [];
  //   for (let i = 0; i < rows; i++) {
  //     let row = [];
  //     for (let j = 0; j < cols; j++) {
  //       row.push(0);
  //     }
  //     board.push(row);
  //   }
  //   console.log(board);
  //   return board;
  // }

  movePlayer = () => {

  }

  componentDidMount() {
    this.setPiece(this.props.player);
  }

  setPiece = (loc) => {
    let brd = this.state.board;
    const row = loc[0];
    const col = loc[1];
    console.log('row: '+row+' col: '+col+' ==='+brd[row][col]);
    brd[row][col] = 'player';
    console.log('setPiece: ',brd);
    this.setState({board: brd});
  }

  renderCell = (cell) => {
    switch(cell) {
      case 0:
        return 'floor';
      case 1:
        return 'wall';
      case 'player':
        return 'player';
      default:
        return 'floor';
    }
  }

  render() {
    return (
      <div className='board'>
      {this.state.board.map((row,i) => {
        return row.map((cell,j) => {
          return (
            <Cell
              key={[i,j]}
              loc={[i,j]}
              type={this.renderCell(cell)}
            />
          );
        })
      })}
      </div>
    );
  }
}

export default Board;

ArrayList list = new ArrayList()在这个泛型为Integer的ArrayList中存放一个String类型的对象

ArrayList list = new ArrayList()在这个泛型为Integer的ArrayList中存放一个String类型的对象

java面试要点---ArrayList list = new ArrayList(); 在这个泛型为Integer的ArrayList中存放一个String类型的对象。

ArrayList list = new ArrayList(); 在这个泛型为Integer的ArrayList中存放一个String类型的对象。 
1.刚刚看到的时候,也是很纳闷后来仔细看了下,java的反射机制;
2.这个可以通过java的反射机制来实现;
3.下面是一个例子:
 package com.credream.refelect;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class TestFile {
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<Integer>(); //定义Integer泛型
String str = "abc"; 
Method[] method=list.getClass().getMethods();//取得list的所有方法
System.out.println(method.length);
for(int i=0;i<method.length;i++){
System.out.println(method[i]);//遍历打印list的方法
}
method[0].invoke(list, str);//通过 反射来执行 list的第一个方法,第一个是list对象,代表该对象的方法,第二个是方法参数:  就是list.add(str);
System.out.println(list.size());
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}
 ------------------------------------------------------------------------------------------------------------------
运行结果:
 35
public boolean java.util.ArrayList.add(java.lang.Object)
public void java.util.ArrayList.add(int,java.lang.Object)
public java.lang.Object java.util.ArrayList.get(int)
public java.lang.Object java.util.ArrayList.clone()
public int java.util.ArrayList.indexOf(java.lang.Object)
public void java.util.ArrayList.clear()
public boolean java.util.ArrayList.contains(java.lang.Object)
public boolean java.util.ArrayList.isEmpty()
public int java.util.ArrayList.lastIndexOf(java.lang.Object)
public boolean java.util.ArrayList.addAll(int,java.util.Collection)
public boolean java.util.ArrayList.addAll(java.util.Collection)
public int java.util.ArrayList.size()
public java.lang.Object[] java.util.ArrayList.toArray(java.lang.Object[])
public java.lang.Object[] java.util.ArrayList.toArray()
public boolean java.util.ArrayList.remove(java.lang.Object)
public java.lang.Object java.util.ArrayList.remove(int)
public java.lang.Object java.util.ArrayList.set(int,java.lang.Object)
public void java.util.ArrayList.ensureCapacity(int)
public void java.util.ArrayList.trimToSize()
public int java.util.AbstractList.hashCode()
public boolean java.util.AbstractList.equals(java.lang.Object)
public java.util.Iterator java.util.AbstractList.iterator()
public java.util.List java.util.AbstractList.subList(int,int)
public java.util.ListIterator java.util.AbstractList.listIterator(int)
public java.util.ListIterator java.util.AbstractList.listIterator()
public java.lang.String java.util.AbstractCollection.toString()
public boolean java.util.AbstractCollection.containsAll(java.util.Collection)
public boolean java.util.AbstractCollection.removeAll(java.util.Collection)
public boolean java.util.AbstractCollection.retainAll(java.util.Collection)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
1
abc

ArrayList在for循环中使用remove方法移除元素方法介绍

ArrayList在for循环中使用remove方法移除元素方法介绍

有时候我们需要在一个ArrayList的for循环中动态删除元素的需求,废话不多说看代码

List<Integer> list = new ArrayList<Integer>(); 
list.add(0); 
list.add(1); 
list.add(2); 
list.add(3); 
list.add(4); 
list.add(5); 
list.add(6); 
list.add(7); 
//正常循环 
for (int i = 0; i < list.size(); i++) { 
 System.out.println("i的值:" + i + " 对应的数字:" + list.get(i)); 
} 
System.out.println("没有remove前list的项:"+list.size()); 
//边循环边删除 
for (int i = 0; i < list.size(); i++) { 
 System.out.println("i的值:" + i + " 对应的数字:" + list.get(i)); 
 if(list.get(i) == 3) list.remove(list.get(i));//删除list的第四项 
} 
System.out.println("remove后list的项:"+list.size()); 
System.out.println("==========remove后的list=========="); 
for (int i = 0; i < list.size(); i++) { 
 System.out.println("i的值:" + i + " 对应的数字:" + list.get(i)); 
} 

执行代码,结果如下:

i的值:0 对应的数字:0 
i的值:1 对应的数字:1 
i的值:2 对应的数字:2 
i的值:3 对应的数字:3 
i的值:4 对应的数字:4 
i的值:5 对应的数字:5 
i的值:6 对应的数字:6 
i的值:7 对应的数字:7 
没有remove前list的项:8 
i的值:0 对应的数字:0 
i的值:1 对应的数字:1 
i的值:2 对应的数字:2 
i的值:3 对应的数字:3 
i的值:4 对应的数字:5 
i的值:5 对应的数字:6 
i的值:6 对应的数字:7 
remove后list的项:7 
==========remove后的list========== 
i的值:0 对应的数字:0 
i的值:1 对应的数字:1 
i的值:2 对应的数字:2 
i的值:3 对应的数字:4 
i的值:4 对应的数字:5 
i的值:5 对应的数字:6 
i的值:6 对应的数字:7 

可以看到没有删除前,我们的list的项和循环对应的数字都是正确的,但是下面的循环在删除第4个元素后,第4,5,6个项对应的数字本应该是4,6,但是这里却变成了5,7.

原因是,我们删除第4项后,list的长度就变成7,而且,list会把第4项后面的值往前移一位,也就是说,i=3时,list.get(i)=4,i=4时,list.get(i)=5,i=5时,list.get(i)=6,i=6时,list.get(i)=7..  我们再说的形象一点,就是本来有8层糕点,依次是0-7,竖起来,大的在上,小的在下,我们从下往上数,数到第5个的时候,吃掉这一层糕点,这时,上面三层分别往下移了一层
所以,值为4的项我们根本没有循环到

那有什么方法可以实现remove呢,有个笨方法,是新建一个tempList,把要删除的项全部add进去,最后用list.removeAll(tempList)实现 . 但是这里我们有更好的方法,就是倒序删除

还是上面的例子,我们看代码:

List<Integer> list = new ArrayList<Integer>(); 
list.add(0); 
list.add(1); 
list.add(2); 
list.add(3); 
list.add(4); 
list.add(5); 
list.add(6); 
list.add(7); 
//正常循环 
for (int i = 0; i < list.size(); i++) { 
 System.out.println("i的值:" + i + " 对应的数字:" + list.get(i)); 
} 
System.out.println("没有remove前list的项:"+list.size()); 
 
//边循环边删除 
for (int i = list.size() -1 ; i >= 0; i--) { 
 System.out.println("i的值 " + i + " 对应的数字 " + list.get(i)); 
 if(list.get(i) == 3) list.remove(list.get(i)); 
} 
System.out.println("remove后list的项:"+list.size()); 
 
System.out.println("==========remove后的list=========="); 
for (int i = 0; i < list.size(); i++) { 
 System.out.println("i的值 " + i + " 对应的数字 " + list.get(i)); 
} 

执行代码,结果如下:

i的值:0 对应的数字:0 
i的值:1 对应的数字:1 
i的值:2 对应的数字:2 
i的值:3 对应的数字:3 
i的值:4 对应的数字:4 
i的值:5 对应的数字:5 
i的值:6 对应的数字:6 
i的值:7 对应的数字:7 
没有remove前list的项:8 
i的值 7 对应的数字 7 
i的值 6 对应的数字 6 
i的值 5 对应的数字 5 
i的值 4 对应的数字 4 
i的值 3 对应的数字 3 
i的值 2 对应的数字 2 
i的值 1 对应的数字 1 
i的值 0 对应的数字 0 
remove后list的项:7 
==========remove后的list========== 
i的值 0 对应的数字 0 
i的值 1 对应的数字 1 
i的值 2 对应的数字 2 
i的值 3 对应的数字 4 
i的值 4 对应的数字 5 
i的值 5 对应的数字 6 
i的值 6 对应的数字 7 

我们可以看到变循环变删除,并不影响后面的元素,remove后的list也和第一次的结果是一样的 . 这是因为我们删除list元素,list的长度是会变小,但是变化的只是比当前被删除元素的项大的项,而我们这里使用倒序循环,大的项,我们已经执行过了,所以不会影响.. 再用上面的比喻来说明,这次我们是从上往下数,数到第4个的时候,上面三层分别往下移了一层,但是这不影响我们之前数过的蛋糕,而且对下面的蛋糕也不影响,这就是原理

总结

以上就是本文关于ArrayList在for循环中使用remove方法移除元素方法介绍的全部内容,希望对大家有所帮助。感兴趣的朋友可以参阅:Java实现跳跃表(skiplist)的简单实例   Java多线程ForkJoinPool实例详解  等。感谢朋友们对编程小技巧网站的支持。有什么问题或者想要了解的可以随时给我们留言,小编会及时回复大家的。

c – 在for循环中重新排序测试条件:编译器错误?

c – 在for循环中重新排序测试条件:编译器错误?

我有一个存储在数组中的树,我正在尝试找到一个特定的节点:
std::vector<Node> nodes = ...
const unsigned short sentinel = -1;
unsigned short index = 0;
for (Node* node = &nodes[index]; // root node
     index != sentinel;
     node = &nodes[index])
{
    if (foo(*node)) {
       index = node->left;
    } else {
       index = node->right;
    }
}

换句话说,没什么特别的.但是,MSVC 2012失败,尝试访问超出范围的节点[sentinel].事实证明,它首先计算& nodes [index],然后测试索引. (调试模式,无优化).

对我来说,这看起来像代码生成错误,但我至少在十年内没有看到过这样的错误.这是简单的未经优化的代码.当然,即使重新排列,在测试索引之前实际上并未使用节点,并且在x86上具有这样的越界指针并不是非常不安全,但是MSVC的向量<>合法地断言该非法指数.

干净的构造并再次检查组件;它是可重复的.树也不是空的,总是有一个根节点.

我忽略了什么,或者这真的是一个严重的编译器错误?

解决方法

你的代码重写为while循环就像
Node* node = &nodes[index]; // root node
while(index != sentinel)
{
    {
        if (foo(*node)) {
           index = node->left;
        } else {
           index = node->right;
        }
    }

    node = &nodes[index];
}

最后一行可能是对节点[-1]的访问.

我会把你的循环改写成

unsigned short index = 0;
do
{
    Node* node = &nodes[index];
    if (foo(*node)) {
       index = node->left;
    } else {
       index = node->right;
    }
} while(index != sentinel);

今天关于在for循环中重新创建ArrayList的最快方法for循环重新循环的介绍到此结束,谢谢您的阅读,有关Array.fill和for循环创建Array有什么区别、ArrayList list = new ArrayList()在这个泛型为Integer的ArrayList中存放一个String类型的对象、ArrayList在for循环中使用remove方法移除元素方法介绍、c – 在for循环中重新排序测试条件:编译器错误?等更多相关知识的信息可以在本站进行查询。

本文标签: