我有一个String列表如下。我想基于此列表是否具有多个具有相同值的元素来进行一些计算。
我有近120k元素,当我运行此代码时,它运行得太慢了。有没有比包含方法更快的方法?
List<String> words= getWordsFromDB(); //words list has nearly 120k elements
List<String> tempWordsList = new LinkedList<String>(); //empty list
String[] keys = getKeysFromDB();
List<String> tempKeysList = new LinkedList<String>();
for (int x = 0; x < words.size(); x++) {
if (!tempWordsList.contains(words.get(x))) {
tempWordsList.add(words.get(x));
String key= keys[x];
tempKeysList.add(key);
} else {
int index = tempWordsList.indexOf(words.get(x));
String m = tempKeysList.get(index);
String n = keys[x];
if (!m.contains(n)) {
String newWord = m + ", " + n;
tempKeysList.set(index, newWord);
}
}
}
编辑:单词列表来自数据库,问题是有服务不断更新并将数据插入此表。我没有任何访问此服务的权限,还有其他应用程序正在使用同一个表。
EDIT2:我已更新完整代码。
答案 0 :(得分:2)
LinkedList.get()
在O(N)时间内运行。使用ArrayList
和O(1)查找时间,或者通过使用迭代器完全避免索引查找:
for (String word : words) {
if (!tempList.contains(word)) {
tempList.add(word);
} else {
int firstIndex = tempList.indexOf(word);
//do some calculations
}
}
免责声明:上述内容是根据words
为LinkedList
的可疑假设撰写的。我仍然会推荐增强型for循环,因为它更常规,其时间复杂度不依赖于实现。无论哪种方式,下面的建议仍然存在。
您可以使用tempList
替换HashMap
来进一步改进。这样可以避免contains()
和indexOf()
:
Map<String, Integer> indexes = new HashMap<>();
int index = 0;
for (String word : words) {
Integer firstIndex = indexes.putIfAbsent(word, index++);
if (firstIndex != null) {
//do some calculations
}
}
根据您的最新更新,您似乎正在尝试对&#34;键&#34;进行分组。通过他们相应的&#34;字&#34;。如果是这样,你可能会给溪流一个旋转:
List<String> words = getWordsFromDB();
String[] keys = getKeysFromDB();
Collection<String> groupedKeys = IntStream.range(0, words.size())
.boxed()
.collect(Collectors.groupingBy(
words::get,
LinkedHashMap::new, // if word order is significant
Collectors.mapping(
i -> keys[i],
Collectors.joining(", "))))
.values();
但是,正如评论中所提到的,最好将此逻辑移到数据库查询中。
答案 1 :(得分:2)
您每个单词都会搜索两次列表:一次用于contains()
,一次用于indexOf()
。您可以将contains()
替换为indexOf()
,将结果测试为-1,否则重复使用结果而不是再次调用indexOf()
。但是你肯定使用了错误的数据结构。您到底需要a
到底是什么? 您需要a
吗?如果您需要将其他数据与每个单词相关联,我会使用HashSet
或HashMap
。
答案 2 :(得分:2)
CString sysCommand;
sysCommand.Format(_T("powershell.exe -executionpolicy unrestricted /C '%s'
%s"), psFile, parameter);
答案 3 :(得分:0)
实际上,tempList
使用线性复杂性时间方法:
if (!tempList.contains(words.get(x))) {
和
int a = tempList.indexOf(words.get(x));
这意味着在每次调用它们时,列表平均迭代为一半
此外,这些都是多余的。
只能调用indexOf()
:
for (int x = 0; x < words.size(); x++) {
int indexWord = tempList.indexOf(words.get(x));
if (indexWord != -1) {
tempList.add(words.get(x));
} else {
//do some calculations by using indexWord
}
}
但要改善所有访问权限,您应该更改结构:将LinkedList
换行或替换为LinkedHashSet
。
LinkedHashSet
将保留实际行为,因为作为List
,它定义了迭代排序,即元素插入集合的顺序,但它也使用散列功能来改进对其元素的时间访问。