如何只返回出现次数最少的字符串ArrayList?

时间:2015-07-11 22:00:27

标签: java android arraylist

我有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和表来减少此方法。不幸的是,我对如何做到这一点感到很茫然。有更好的方法吗?

5 个答案:

答案 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>

类型

现在,让我们迭代你的收藏:

  1. 从您的收藏中获取另一个字符串
  2. 检查HashMap中是否存在字符串(#contains)
  3. 如果不存在,请使用String键添加新元素(hashMap.put(stringKey,1);
  4. 如果存在,则使用相同的键放置元素,但增加内部计数器(hashMap.put(stringKey,hashMap.get(stringKey)+1)
  5. 继续
  6. 现在你有一个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 stepsAVL Tree步骤为O(Log (1,000,000))步,非常整齐。如果您的数据是动态的,这将是一个很好的方法,尽管您必须优化插入。

使用AVL树,所有内容都会被排序,因此您获得== 6时间。而不是遍历O(Log N)这样的数组:

enter image description here

你可以这样:

enter image description here

检查根目录并看到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);
}

按预期生成输出: