我有一个包含305899个字符串的列表(这是一个网站的用户名)。删除所有重复项后,数字将下降到172123字符串。
我想查找在该ArrayList中重复特定字符串(用户名)的次数。我写了一个简单的冒泡排序类型逻辑,但它太慢了。
private static Map<String, Integer> findNumberOfPosts(List<String> userNameList) {
Map<String, Integer> numberOfPosts = new HashMap<String, Integer>();
int duplicate = 0;
int size = userNameList.size();
for (int i = 0; i < size - 1; i++) {
duplicate = 0;
for (int j = i + 1; j < size; j++) {
if (userNameList.get(i).equals(userNameList.get(j))) {
duplicate++;
userNameList.remove(j);
j--;
size--;
}
}
numberOfPosts.put(userNameList.get(i), duplicate);
}
return numberOfPosts;
}
然后我改为:
private static Map<String, Integer> findNumberOfPosts(List<String> userNameList) {
Map<String, Integer> numberOfPosts = new HashMap<String, Integer>();
Set<String> unique = new HashSet<String>(userNameList);
for (String key : unique) {
numberOfPosts.put(key, Collections.frequency(userNameList, key));
}
return numberOfPosts;
}
这也很慢。当我的意思是缓慢时,通过列表需要30多分钟。
还有其他有效方法可以解决这个问题吗?只需减少查找和计算重复元素所需的时间吗?
答案 0 :(得分:4)
您的findNumberOfPosts
方法正确,但您的实施正在进行大量不必要的工作
试试这个:
private static Map<String, Integer> findNumberOfPosts(List<String> userNameList) {
Map<String, Integer> numberOfPosts = new HashMap<String, Integer>();
for (String userName : userNameList) {
Integer count = numberOfPosts.get(userName);
numberOfPosts.put(userName, count == null ? 1 : ++count);
}
return numberOfPosts;
}
这应该在大多数机器上执行几秒钟。
答案 1 :(得分:3)
查看第二种方法的这种变化是否更快:
private static Map<String, Integer> findNumberOfPosts(
List<String> userNameList) {
Map<String, Integer> numberOfPosts = new HashMap<String, Integer>();
for (String name : userNameList) {
Integer count = numberOfPosts.get(name);
numberOfPosts.put(name, count == null ? 1 : (1 + count));
}
return numberOfPosts;
}
它有一些装箱/拆箱开销,但应该比你正在进行的操作快得多,这需要迭代每个唯一名称的整个名称列表。
答案 2 :(得分:2)
您可以尝试使用用户名构建Trie
结构。然后找到不同元素的数量(用户名)将是微不足道的。 Trie的代码有点复杂,所以你最好查看资源,看看如何完成实现。
另一方面,考虑到实际情况,您不应该首先拥有此重复列表。我的意思是,如果提供用户名的系统设计得当,那么首先不会存在重复项。
答案 3 :(得分:1)
这比波西米亚人更快:
private static Map<String, Integer> findNumberOfPosts(List<String> userNameList) {
Map<String, Integer> numberOfPosts = new HashMap<String, Integer>();
for (String userName : userNameList) {
if (!numberOfPosts.containsKey(userName)) {
numberOfPosts.put(userName, Collections.frequency(userNameList, userName));
}
}
return numberOfPosts;
}
答案 4 :(得分:0)
最佳解决方案是将所有元素添加到Array中,然后对该数组进行排序。
然后你可以迭代数组,重复项将在数组中彼此相邻放置。
答案 5 :(得分:0)
您应该尝试改进第一个实现:对于每个条目,您将遍历整个列表。怎么样:
Map<String, Integer> map;
for (String username : usernames) {
if (!map.containsKey(username)) {
map.put(username, new Integer(0));
} else {
map.put(username, new Integer(map.get(username).intValue() + 1));
}
}
return map;
答案 6 :(得分:0)
使用旨在本机支持此功能的数据结构。将用户名存储在Multiset中,让它自动为您保留频率/计数。
阅读this tutorial以了解multiset的工作方式/
答案 7 :(得分:0)
以下是删除重复项并计算List中重复元素数的最佳方便方法。无需额外的逻辑。
List<String> userNameList = new ArrayList<String>();
// add elements to userNameList, including duplicates
userNameList.add("a");
userNameList.add("a");
userNameList.add("a");
userNameList.add("a");
userNameList.add("b");
userNameList.add("b");
userNameList.add("b");
userNameList.add("b");
userNameList.add("c");
userNameList.add("c");
userNameList.add("c");
userNameList.add("c");
int originalSize=userNameList.size();
HashSet hs = new HashSet(); //Set would handle the duplicates automatically.
hs.addAll(userNameList);
userNameList.clear();
userNameList.addAll(hs);
Collections.sort(userNameList); //Sort the List, if needed.
//Displays elements after removing duplicate entries.
for(Object element:userNameList)
{
System.out.println(element);
}
int duplicate=originalSize-userNameList.size();
System.out.println("Duplicate entries in the List:->"+duplicate); //Number of duplicate entries.
/*Map<String, Integer> numberOfPosts = new HashMap<String, Integer>(); //Store duplicate entries in your Map using some key.
numberOfPosts.put(userNameList.get(i), duplicate);
return(numberOfPosts);*/