【问题标题】:Faster way to find index of String in ArrayList在 ArrayList 中查找字符串索引的更快方法
【发布时间】:2015-08-11 09:53:58
【问题描述】:

所以我有这样的事情:

List<String> test = new ArrayList<String>();

当我打印它时,我有:

"[ABC, DEF, GHI, JKL]"

我想搜索“E”的示例索引。我是这样做的:

for (String a : test) {
   if(a.contains("E")) {
      System.out.println(test.indexOf(a));
   }
}

有更快的方法吗?因为现在我每时每刻都在所有名单上都写“for”。

【问题讨论】:

  • 列表是否有序?
  • 您要查找数组列表中包含“E”的所有项目,还是只查找第一个?
  • 你能改变保存数据的结构吗?不是一个数组列表,而是一个带有键的映射 - 英文字母表的 26 个字母?
  • 是的,我只想要第一个包含“E”的元素。

标签: java list indexof


【解决方案1】:

您可以使用置换索引,通常用于单词:

["he speaks well", "well done"]

会给出一个排序列表

     well *done*
          *he* speaks well
       he *speaks* well
he speaks *well*
          *well* done

你可以快速找到“好”的地方。

在我们的例子中,这样的列表条目将是:

class Entry implements Comparable<Entry> {
    String right;
    String left;

    @Override
    public String toString() { return left + "^" + right; }
}

对于每个长度为 N 的字符串,都有 right 个值,分别为 N、N-1、...、2、1 个字符。

class SearchBase {
    private List<Entry> entries; // Or immediately sorted: TreeSet

    void addAll(String... terms) {
        fill list entries, and sort them
    }

    Collection<String> termsContaining(String sought) {
        binary search on entries rigth
    }
}

【讨论】:

    【解决方案2】:

    鉴于您已经说过要查找列表中包含“E”的第一个项目,根据定义,您必须遍历每个项目以检查它们,直到找到匹配项 - 这可能在最后列表,所以在最坏的情况下,您仍然必须搜索整个列表。

    但是,您可以采取的一种捷径是至少在找到您感兴趣的那个后立即退出循环:

    for (String a : test) {
       if(a.contains("E")) {
          System.out.println(test.indexOf(a));
          break;
       }
    }
    

    如果您正在搜索一个完整的字符串(例如“ABC”),您可以使用 indexOf,但是当您正在搜索部分匹配时,您不能这样做。

    Java 8 语法虽然不太可能提高性能或以更少的代码行执行操作,但可以说更具可读性,并且允许您链接其他流操作以对匹配的项目执行任何您需要执行的操作查询:

    List<String> list = Arrays.asList("ABC", "DEF", "GHI", "JKL");
    Optional<String> matchingItem = list.stream()
                                        .filter(s -> s.contains("E"))
                                        .findFirst();
    matchingItem.ifPresent(s -> System.out.println(list.indexOf(s)));
    

    Java 8 确实包含对此类操作的优化。

    顺便说一句,如果您的列表非常大,您可能会发现使用 parallelStream() 而不是 stream() 可以提高速度 - 此 Java 8 代码可能与您的代码执行相同数量的操作,但它可以在多个没有传统 for 循环的 CPU 内核。

    或者,如果您确实需要一种立即访问所需元素的方法,并且您正在寻找的标准始终相同(即您总是只需要包含“E”的元素) ,您可以在其他数据结构(如地图)中跟踪数据。例如。每次将项目添加到包含所需条件的列表时,您也会将其添加到地图中。比如:

    Map<String, List<String>> mapOfValuesICareAbout = new HashMap<>();
    String newValue = "GFE";
    if (newValue.contains("E")) {
        mapOfValuesICareAbout.get("E").add(newValue);
    }
    list.add(newValue);
    

    【讨论】:

    • Is any faster way to do this? 这意味着他想要一种更快的方法而不是更清洁的方法。
    • 明白,但在我回答的开头,我声明根据定义没有更快的方法。
    【解决方案3】:

    如果您只想要包含字母“E”的第一个元素的索引,您可以只使用String#indexOf(char) 来节省一个操作。找到元素后,您可以跳出循环。

    List<String> test = Arrays.asList("ABC", "DEF", "GHI", "JKL");
    for (String element : test) {
        int idx = element.indexOf('E');
        if (idx != -1) {
            System.out.println(element + " with 'E' at pos: " + idx);
            break;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-02-05
      • 2018-12-23
      • 2012-01-16
      • 1970-01-01
      • 2012-10-31
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多