11

首先,如果我错了,请纠正我。我想在ArrayList<CustomType>不使用 For 循环的情况下查找项目的索引(即字符串值)。

POJO:

id;
name;

代码:

ArrayList<POJO> list = new ArrayList<POJO>;

//Lots of data added to these list...

现在我想从 arraylist 中找到特定名称的 id,而不使用下面的 for 循环。

String id = null;
// TODO Auto-generated method stub
for (int i = 0; i < list.size(); i++) {
    if("ABCD".equalsIgnoreCase(list.get(i).getName())) {
        id = list.get(i).getId();
        break;
    }
}

理想情况下,我不想实现 For 循环,因为在某些情况下,我在 List 中有 500 多个数据,并且使用 For 循环查找索引并不是一个好方法。

4

6 回答 6

12

您可以使用list.indexOf(),但为了使其工作,您需要覆盖equalshasCodePOJO.

默认情况下,如果两个对象具有相同的引用,则它们将被视为相等。您可以覆盖equals为您的案例工作:

public boolean equals(Object o) {
  if (!(o instanceof POJO)) {
    return false;
  }
  POJO other = (POJO) o;
  return name.equalsIgnoreCase(other.getName());
}

覆盖 equals 会建议你覆盖hashCode. 例如:

public int hashCode() {
  return name.hashCode();
}
于 2012-11-12T09:48:46.983 回答
4

以这种方式找到复杂性会给您带来 BIG-O (n) 的元素。我认为,如果您使用地图,那会给您带来更好的结果。

HashMap会是更好的选择。- 复杂度为 O(1)。

于 2012-11-12T09:48:39.533 回答
3

谢谢大家的友好和快速的回​​应。但要特别感谢Joachim Sauer。您绝对正确,500 个元素并不多,这个循环很可能对您的代码性能没有真正的影响(即使它效率低下)。即使我尝试了多达 5000 个元素,但仍然对性能没有负面影响。

再次感谢大家,并感谢您对Joachim Sauer的评论。

于 2012-11-13T13:40:09.127 回答
2

如果您需要搜索字符串值,您应该使用 aHashMap而不是ArrayList.

于 2012-11-12T09:48:37.173 回答
2

你可以使用List.indexOf()- 但你必须确保你也覆盖POJO.equals()- (并且作为约定的一部分 - 也是hashCode().

请注意,尽管如此 - 结果将是O(n)- 一种替代方法可能是使用排序数组( POJO[]) 并使用Arrays.binarySearch()Set/ Map

如果您使用数组并且binarySearch()- 您必须确保它POJO也实现Comparable<POJO>


请注意,对于静态数据(您的列表不会经常/根本不更改) - 尽管数组并且binarySearch()“更糟糕”然后HashSet就大 O 表示法而言,实际上 - 它通常要快得多,尤其是对于相对较短的列表。
就大 O 表示法而言,基于散列的解决方案提供了O(1)平均案例访问。

于 2012-11-12T09:49:03.640 回答
0

为了回答这个问题,我使用 JMH 启动了一个基准测试。

毫无疑问,经典循环是做到这一点的有效方法。

我使用了DATA_ARRAY包含 17576 个元素的 a,搜索到的元素位于索引 7733 处。

使用经典循环 - 0,030 ± 0,001 ms/op:

int i = 0;
for (String str : DATA_ARRAYLIST) {
    if (str.equals("lll")) break;
    i++;
}

使用 indexOf 并覆盖 equals 方法:0,030 ± 0,002 ms/op

MY_DATA_ARRAYLIST.indexOf("lll");

使用数据范围:0,082 ± 0,003 ms/op

OptionalInt integer = IntStream.range(0, DATA_ARRAYLIST.size())
            .filter(i -> DATA_ARRAYLIST.get(i).equals("lll"))
            .findFirst();

在找到流后使用 indexOf:0,074 ± 0,008 ms/op

String result = DATA_ARRAYLIST.stream().filter(e -> e.equals("lll")).findFirst().get();
DATA_ARRAYLIST.indexOf(result);

找到并行流后使用 indexOf:0,087 ± 0,023 ms/op

String result = DATA_ARRAYLIST.parallelStream().filter(e -> e.equals("lll")).findFirst().get();
DATA_ARRAYLIST.indexOf(result);

但是,如果搜索到的元素在最后一个索引中:

  • 经典循环:0,066 ± 0,002 毫秒/操作
  • 并行流:0,121 ± 0,023 ms/op
  • 流:0,161 ± 0,024 毫秒/操作

然后如果你有 456 976 个元素:

  • 经典循环:2,172 ± 0,297 毫秒/操作
  • 并行流:3,145 ± 0,380 ms/op
  • 流:6,081 ± 0,097 毫秒/操作

如您所见,击败 Loop 真的很难!

于 2020-08-20T17:46:19.767 回答