我有String[]
,originalStringArray
,其中有重复项。所以{"dog","cat","dog","fish","dog","cat"}
。
我想创建一个只返回恰好发生一定次数的字符串的函数。在这里,如果我说3,它将返回“狗”而不是“猫”。
这是我目前的代码:
public ArrayList<String> returnMultiples(String[] originalStringArray,int requiredCount){
ArrayList<Integer> mCount = new ArrayList<>();
List<String> list = Arrays.asList(originalStringArray);
ArrayList<String> result = new ArrayList<>();
// Count occurrences in original string
for(String item: originalStringArray){
mCount.add(Collections.frequency(list,item));
}
// If frequency is equal to count, add to array list
for(int i=0; i<mCount.size(); i++){
if(mCount.get(i) == requiredCount){
result.add(originalStringArray[i]);
}
}
return result;
}
我遇到的问题是,我在某处读到了Collections库非常慢并且拖动,并且似乎可以使用HashSets和表来减少此方法。不幸的是,我对如何做到这一点感到很茫然。有更好的方法吗?
答案 0 :(得分:3)
需要某种地图才能实现这一目标。以下是使用HashMaps编写的示例:
public ArrayList<String> returnMultiples(String[] array, int min){
HashMap<String, Integer> counts = new HashMap<String, Integer>();//instantiate a new HashMap
//loop through the array and count the occurrences of each different string in the array
for(int i = 0; i < array.length; i++){
String word = array[i];
if(counts.containsKey(word))
counts.put(word, counts.get(word) + 1);
else
counts.put(word, 1);
}
ArrayList<String> multiples = new ArrayList<String>();
//check if any of the words occur >= min times. if so, add them to the returning list.
for(String key : counts.keySet()){
if(counts.get(key) >= min){
multiples.add(key);
}
}
return multiples;//return the list we just created of the desired strings
}
根据字符串的长度,HashMap比使用集合更有效,尽管差异几乎可以忽略不计。
答案 1 :(得分:2)
您必须使用HashMap
执行此任务。
假设您的HashMap
将包含给定字符串的出现次数,因此它将为HasMap<String,Integer>
现在,让我们迭代你的收藏:
现在你有一个hashmap包含你的集合中给定字符串的确切出现次数。
快速查找将创建反向HashMap<Integer,String>
,但计数可能会重复,这不会起作用。要获取出现的字符串与给定字符串匹配,您必须迭代映射的所有键,并仅返回出现次数与您的条件匹配的那些。
答案 2 :(得分:1)
您的算法将返回重复项。
HashSet 是收藏库的一部分,所以没有优势。
包含Collections.frequency的循环是一种O(n ^ 2)算法。 (对于originalStringArray中的每个String,Collections.frequency再次遍历整个originalStringArray)。
你只能使用HashMap。
为originalStringArray中的每个String增加地图中的整数。
删除所有值与requiredCount不同的键。
如果您确实想要返回一个ArrayList,请将map.keySet()添加到新的ArrayList。
或map.keySet()。toArray(String [map.size()])如果你想要一个数组。
答案 3 :(得分:1)
您可以使用function checkBoth() {
document.getElementById('c1').checked = true;
document.getElementById('c2').checked = true;
}
,前提是如果你让数组中有1,000,000个项目,那么AVL Tree
需要通过该数据结构。使用1,000,000 steps
,AVL Tree
步骤为O(Log (1,000,000))
步,非常整齐。如果您的数据是动态的,这将是一个很好的方法,尽管您必须优化插入。
使用AVL树,所有内容都会被排序,因此您获得== 6
时间。而不是遍历O(Log N)
这样的数组:
你可以这样:
检查根目录并看到N Steps
c大于Char
中的第一个Char
,然后横向移动。基本上按dog
每个步骤缩短搜索时间,使其成为1/2
步。你必须保持树高平衡。
关于O(Log N)
的好处是,您的数据始终按排序顺序排列,因为树需要平衡。
如果数据不经常改变,而您不需要排序数据,那么使用AVL Tree
可能会更好。
答案 4 :(得分:1)
我想,足够有效的是使用哈希映射。
进入我脑海中的最短代码(以及使用HashMaps的代码)将如下所示:
String[] filter(String[] collection, int requirement) {
final HashMap<String, Integer> temp = new HashMap<>();
for (String item : collection) {
int current = temp.getOrDefault(item, 0);
temp.put(item, ++current);
}
final Iterator<Entry<String, Integer>> iterator = temp.entrySet().iterator();
while (iterator.hasNext()) {
final Entry<String, Integer> entry = iterator.next();
if (entry.getValue() != requirement) {
iterator.remove();
}
}
return temp.keySet().toArray(new String[temp.size()]);
}
可以使用的内容如下:
final String[] array = new String[]{
"dog", "dog", "dog", "cat", "cat", "fish", "cat"
};
final String[] result = filter(array, 3);
for (String item : result) {
System.out.println(item);
}
按预期生成输出:
猫
狗