Я продолжаю получать первый объект в списке, когда я пытаюсь выполнить итерацию.
код:
@Override
protected void onPostExecute(List<Location> locations) {
// TODO Auto-generated method stub
super.onPostExecute(locations);
Log.d("Debug" , "List: " + locations.size() + " markers");
for (Location location : locations) {
Log.d("Debug", "index of: " + locations.indexOf(location));
}
}
Распечатка говорит, что 200 маркеров в списке и распечатке индекса дают "0" 200 раз. Почему он не будет переходить к следующему объекту?
.indexOf()
просто рассматривает каждый объект в каждом индексе как .equals(location)
== true
для первого в индексе 0
.
Если вы добавили одно и то же Location
200 раз, а .equals()
не будет правильно переопределено; например, если каждый экземпляр равен каждому другому экземпляру; вы вернетесь в первый матч.
В List.indexOf(Object o) Javadoc четко указано:
Возвращает индекс первого вхождения указанного элемента в этом списке или
-1
если этот список не содержит этот элемент. Более формально возвращает наименьший индекс я такой, что(o==null? get(i)==null: o.equals(get(i)))
или-1
если такого индекса нет.
.equals()
думает, значит, вы получите первый матч. В вашем случае индекс 0
.
public static void main(final String[] args)
{
final List<String> al = new ArrayList<String>(100);
for (int i=0; i<100; i++) { al.add("Hello World!"); }
for (final String s : al)
{
System.out.println(al.indexOf(s));
}
}
Распечатывается 0
100 раз.
Одно простое изменение
for (int i=0; i<100; i++) { al.add(Integer.toString(i)); }
И вы видите, что код работает по назначению с уникальными объектами, которые рассматриваются правильно реализованным .equals()
Location
считаются значимо равными.
.equals()
не ведет себя правильно в их случае.
Вероятно, потому что indexOf()
возвращает первый индекс экземпляра объекта, который equals()
объекту, который вы проверяете, и у вас должно быть много разных Location
, которые считаются значимо равными. Это может быть связано с тем, что вы неправильно переопределили метод equals для Location
или просто не рассматривали последствия вашего конкретного переопределения.
Взгляните на следующий пример, демонстрирующий вашу проблему, за исключением объектов String
;
ArrayList<String> als = new ArrayList<String>();
als.add("a");
als.add("b");
als.add("c");
als.add("d");
als.add("e");
for(String s : als) System.out.print(als.indexOf(s));
als = new ArrayList<String>();
als.add(new String("a"));
als.add(new String("a"));
als.add(new String("a"));
als.add(new String("a"));
als.add(new String("a"));
System.out.println();
for(String s : als) System.out.print(als.indexOf(s));
Это результаты;
01234
00000
В последние 5 выводимые 0
с, s
String
вы проверить массив для может быть второй или более String
в массиве, но он оказывается по значению равно (как определено String
классов equals()
внахлест) в String
в первый индекс, и поэтому он всегда будет возвращать 0
. Попробуйте приведенный выше пример с массивом объектов вместо этого, и они никогда не считаются равными, если они не относятся к одному и тому же объекту в памяти.
Подтвердить метод равенства или проверить, что экземпляр не является нулевым. Это реализация метода на ArrayList, чтобы понять, почему.
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Обычно for (Location location: locations)
выполняется indexOf()
по объектам в списке мест. Когда вызывается indexOf()
он использует equals и hashCode для поиска конкретного объекта, но я думаю, что вы не реализуете методы equals
и hashCode
класса Location. Попробуйте выполнить их и проверить.