ArrayLists лучше практиковать - PullRequest
1 голос
/ 20 апреля 2020

Я написал 2 метода в Java. Второй метод выглядит для меня чище, потому что я пришел из python фона, но я думаю, что он будет медленнее, чем первый, потому что indexOf () также выполняет итерацию? Есть ли способ использовать в l oop правильно в такой ситуации? Кроме того, если есть лучший способ сделать это (без потоков), как это можно сделать?

private ArrayList<MyObject> myObjects;

Первый метод:

private int findObject(String objectName) {
    for(int i=0; i<this.myObjects.size(); i++) {
        MyObject myObject = this.myObjects.get(i);
        if(myObject.getName().equals(objectName)) return i;
    }
    return -1;
}

Второй метод:

private int findObject(String objectName) {
    for(MyObject myObject: this.myObjects) {
        if(myObject.getName().equals(objectName)) return this.myObjects.indexOf(myObject);
    }
    return -1;
}

Ответы [ 3 ]

2 голосов
/ 20 апреля 2020

Я думаю, что это будет медленнее, чем первое, потому что indexOf () также выполняет итерацию?

Вы правы.

Есть ли способ правильно использовать for each l oop в подобной ситуации?

Вы можете использовать for each И индексную переменную.

private int findObject(String objectName) {
    int i = 0;
    for (MyObject myObject: this.myObjects) {
        if (myObject.getName().equals(objectName)) return i;
        i++;
    }
    return -1;
}

Это было бы хорошим решением, если myObjects.get(i) является дорогостоящей операцией (например, на LinkedList, где get(n) равно O(N)) или если она не реализуема (например, если вы выполняли итерацию a Stream).

Вы также можете использовать ListIterator при условии , что myObjects имеет метод, который возвращает ListIterator; см. пример @ 1028 * ответа Энди Тернера. (Это не будет работать для типичного Set или Map класса.)

2 голосов
/ 20 апреля 2020

Первая версия идеально подходит , если вы знаете, что работаете с ArrayList (или каким-либо другим списком на основе массива, например Vector).

Если myObject окажется LinkedList или подобное, ваша производительность будет ухудшаться с более длинными списками, так как тогда get(i) больше не будет выполняться в постоянное время.

Ваш второй подход будет обрабатывать LinkedList с, а также ArrayList с, но он повторяется дважды по вашему списку, один раз в вашем for l oop и один раз в вызове indexOf().

Я бы порекомендовал третью версию: используйте for для l oop из второго подхода и добавьте целочисленную переменную для подсчета, увеличивая ее до l oop. Таким образом, вы получаете лучшее из обоих: итерацию без снижения производительности и дешевый подсчет позиций.

1 голос
/ 20 апреля 2020

Лучший способ сделать это (избегающий необходимости поддерживать отдельную переменную индекса и работающий также и со списками, отличными от RandomAccess) - использовать ListIterator:

for (ListIterator<MyObject> it = myObjects.listIterator(); it.hasNext();) {
  MyObject myObject = it.next();
  if(myObject.getName().equals(objectName)) return it.prevIndex();
}
return -1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...