【发布时间】:2018-07-15 18:04:06
【问题描述】:
我有一个巨大的字符串列表 (List<String>),其中可能包含超过 10.000 个唯一元素(字符串),我需要参考这个列表多对多(可能超过 10.000 ,也是)在循环中确定列表是否包含某些元素。
例如:
/**
* The size of this list might be over 10.000.
*/
public static final List<String> list = new ArrayList<>();
<...>
/**
* The size of the 'x' list might be over 10.000, too.
*
* This method just does something with elements in the list 'x'
* which are not in the list 'list' (for example (!), just returns them).
*/
public static List<String> findWhatsNotInList(List<String> x) {
List<String> result = new ArrayList<>();
for (String s : x) {
if (list.contains(s))
continue;
result.add(s);
}
return result;
}
<...>
根据list 和x 列表的大小,此方法可能会执行几分钟,这太长了。
有没有办法加快这个过程? (在完全替换 List 并循环使用其他内容时,请随意提出任何内容。)
编辑:尽管使用了List#contains 方法,但我可能需要使用List#stream 并进行一些检查,而不仅仅是String#equals(例如使用startsWith)。例如:
/**
* The size of this list might be over 10.000.
*/
public static final List<String> list = new ArrayList<>();
<...>
/**
* The size of the 'x' list might be over 10.000, too.
*
* This method just does something with strings in the list 'x'
* which do not start with any of strings in the list 'list' (for example (!), just returns them).
*/
public static List<String> findWhatsNotInList(List<String> x) {
List<String> result = new ArrayList<>();
for (String s : x) {
if (startsWithAny(s, list))
continue;
result.add(s);
}
return result;
}
<...>
/**
* Check if the given string `s` starts with anything from the list `list`
*/
public boolean startsWithAny(String s, List<String> sw) {
return sw.stream().filter(s::startsWith).findAny().orElse(null) != null;
}
<...>
编辑#2:一个例子:
public class Test {
private static final List<String> list = new ArrayList<>();
static {
for (int i = 0; i < 7; i++) {
list.add(Integer.toString(i));
}
}
public static void main(String[] args) {
List<String> in = new ArrayList<>();
for (int i = 0; i < 10; i++)
in.add(Integer.toString(i));
List<String> out = findWhatsNotInList(in);
// Prints 7, 8 and 9 — Strings that do not start with
// 0, 1, 2, 3, 4, 5, or 6 (Strings from the list `list`)
out.forEach(System.out::println);
}
private static List<String> findWhatsNotInList(List<String> x) {
List<String> result = new ArrayList<>();
for (String s : x) {
if (startsWithAny(s, list))
continue;
result.add(s);
}
return result;
}
private static boolean startsWithAny(String s, List<String> sw) {
return sw.stream().filter(s::startsWith).findAny().orElse(null) != null;
}
}
【问题讨论】:
-
你考虑过
List以外的其他数据结构吗? -
是否可以将“列表”设为集合而不是列表。列表中包含的方法需要 O(N) 才能运行,其中 Set 有 O(1)。
-
编辑了帖子:我实际上需要通过列表
list进行流式传输并执行startsWith,而不仅仅是contains。我很抱歉。 -
对于startsWith,您可以先订购您的数据。
标签: java list arraylist bigdata