如何获取ArrayList中元素出现的次数

Gar*_*rik 1 java collections list

    for(int i=0; i<arr.size(); ++i){
        oc = Collections.frequency(arr, arr.get(i));
        System.out.print(oc + " "+ arr.get(i) +" ");
        arr.remove(i);
    }
Run Code Online (Sandbox Code Playgroud)

主要思想是输出序列中每个元素出现的次数.例如

1 1 2 3 3 3 10 10
Run Code Online (Sandbox Code Playgroud)

这里的输出是

2 1 1 2 3 3 2 10
Run Code Online (Sandbox Code Playgroud)

它就像两个,一个元素为两个,3个元素为3,2个元素为10.

这是有缺陷的,例如它不适用于这种情况

1 1 1 2 2 1 1 1 
Run Code Online (Sandbox Code Playgroud)

怎么了?还有其他算法吗?

icz*_*cza 6

问题是在for循环内部删除了一个元素(arr.remove(i)),以便其余的元素被移位,当i增加时,你跳过一个元素.删除元素也会改变其频率,因此不要这样做.

做这样的事情:

List<String> arr = Arrays.asList("a", "a", "b", "a", "a");

for (String s : arr)
    System.out.println("element: " + s
        + ", count: " + Collections.frequency(arr, s));
Run Code Online (Sandbox Code Playgroud)

如果元素多次出现在列表中,则会多次打印.使用a HashSet来记住元素是否已经打印过,不要再次打印:

List<String> arr = Arrays.asList("a", "a", "b", "a", "a");

Set<String> printed = new HashSet<>();
for (String s : arr) {
    if (printed.add(s)) // Set.add() also tells if the element was in the Set!
        System.out.println("element: " + s
            + ", count: " + Collections.frequency(arr, s));
}
Run Code Online (Sandbox Code Playgroud)

输出:

element: a, count: 4
element: b, count: 1
Run Code Online (Sandbox Code Playgroud)

替代

或者,您可以将原始列表的所有元素添加到Set(这将确保每个元素仅包含一次),并迭代此集合,但在原始数组中计数:

List<String> arr = Arrays.asList("a", "a", "b", "a", "a");

for (String s : new HashSet<>(arr))
    System.out.println("element: " + s
        + ", count: " + Collections.frequency(arr, s));
Run Code Online (Sandbox Code Playgroud)

输出:相同.但请注意,这可能会导致输出的顺序不同,因为SetJava中的s不是有序的.