web-dev-qa-db-de.com

Wie zählt man die Anzahl der Vorkommen eines Elements in einer Liste?

Ich habe eine ArrayList, eine Collection-Klasse von Java, wie folgt:

ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");

Wie Sie sehen, besteht die animalsArrayList aus 3 bat Elementen und einem owl Element. Ich habe mich gefragt, ob es eine API im Collection-Framework gibt, die die Anzahl der bat-Vorkommen zurückgibt, oder ob es eine andere Möglichkeit gibt, die Anzahl der Vorkommen zu bestimmen.

Ich habe festgestellt, dass die Google-Kollektion Multiset über eine API verfügt, die die Gesamtzahl der Vorkommen eines Elements zurückgibt. Das ist aber nur mit JDK 1.5 kompatibel. Unser Produkt ist derzeit in JDK 1.6, daher kann ich es nicht verwenden.

150
MM.

Ich bin mir ziemlich sicher, dass die statische Frequenzmethode in Collections hier nützlich sein würde:

int occurrences = Collections.frequency(animals, "bat");

So würde ich es trotzdem machen. Ich bin mir ziemlich sicher, dass dies jdk 1.6 ist.

292
Lars Andren

In Java 8:

Map<String, Long> counts =
    list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
72

Dies zeigt, warum es wichtig ist, " Verweise auf Objekte anhand ihrer Schnittstellen " wie in Effective Java book beschrieben.

Wenn Sie Code für die Implementierung codieren und ArrayList in beispielsweise 50 Stellen in Ihrem Code verwenden, wenn Sie eine gute "List" -Implementierung finden, die die Elemente zählt, müssen Sie all diese 50 Orte ändern und müssen dies möglicherweise tun brechen Sie Ihren Code (wenn er nur von Ihnen verwendet wird, gibt es keine große Sache, aber wenn er von einer anderen Person verwendet wird, brechen Sie auch ihren Code) 

Durch die Programmierung der Schnittstelle können Sie diese 50 Stellen unverändert lassen und die Implementierung von ArrayList durch "CountItemsList" (beispielsweise) oder eine andere Klasse ersetzen.

Nachfolgend finden Sie ein sehr einfaches Beispiel, wie dies geschrieben werden könnte. Dies ist nur ein Beispiel, eine produktionsbereite Liste wäre viel komplizierter.

import Java.util.*;

public class CountItemsList<E> extends ArrayList<E> { 

    // This is private. It is not visible from outside.
    private Map<E,Integer> count = new HashMap<E,Integer>();

    // There are several entry points to this class
    // this is just to show one of them.
    public boolean add( E element  ) { 
        if( !count.containsKey( element ) ){
            count.put( element, 1 );
        } else { 
            count.put( element, count.get( element ) + 1 );
        }
        return super.add( element );
    }

    // This method belongs to CountItemList interface ( or class ) 
    // to used you have to cast.
    public int getCount( E element ) { 
        if( ! count.containsKey( element ) ) {
            return 0;
        }
        return count.get( element );
    }

    public static void main( String [] args ) { 
        List<String> animals = new CountItemsList<String>();
        animals.add("bat");
        animals.add("owl");
        animals.add("bat");
        animals.add("bat");

        System.out.println( (( CountItemsList<String> )animals).getCount( "bat" ));
    }
}

Angewandte OO-Prinzipien: Vererbung, Polymorphismus, Abstraktion, Verkapselung.

21
OscarRyz

In der Collections-Klasse gibt es eigentlich eine statische Methode: frequency (Collection c, Object o), die die Anzahl der Vorkommen des gesuchten Elements zurückgibt. Übrigens, das funktioniert perfekt für Sie: 

ArrayList<String> animals = new ArrayList<String>();
animals.add("bat");
animals.add("owl");
animals.add("bat");
animals.add("bat");
System.out.println("Freq of bat: "+Collections.frequency(animals, "bat"));
12
Khafaga

Entschuldigung, es gibt keinen einfachen Methodenaufruf, der das ausführen kann. Sie müssen jedoch nur eine Karte erstellen und die Häufigkeit zählen.

HashMap<String,int> frequencymap = new HashMap<String,int>();
foreach(String a in animals) {
  if(frequencymap.containsKey(a)) {
    frequencymap.put(a, frequencymap.get(a)+1);
  }
  else{ frequencymap.put(a, 1); }
}
11
Ray Hidayat

Es gibt keine native Methode in Java, die das für Sie tun kann. Sie können jedoch IterableUtils # countMatches () aus Apache Commons-Collections verwenden, um dies für Sie auszuführen.

9
Kevin

Ich frage mich, warum Sie diese Sammlungs-API von Google nicht mit JDK 1.6 verwenden können. Sagt es so? Ich denke, Sie können, es sollte keine Kompatibilitätsprobleme geben, da es für eine niedrigere Version ausgelegt ist. Der Fall wäre anders gewesen, wenn diese für 1.6 erstellt wurden und Sie 1.5 verwenden.

Irre ich mich irgendwo?

8
Adeel Ansari

Ein etwas effizienterer Ansatz könnte sein

Map<String, AtomicInteger> instances = new HashMap<String, AtomicInteger>();

void add(String name) {
     AtomicInteger value = instances.get(name);
     if (value == null) 
        instances.put(name, new AtomicInteger(1));
     else
        value.incrementAndGet();
}
6
Peter Lawrey

Alternative Java 8 Lösung mit Streams :

long count = animals.stream().filter(animal -> "bat".equals(animal)).count();
6
R O M A N I A

Was Sie wollen, ist eine Tasche - die wie ein Set ist, aber auch die Anzahl der Vorkommnisse zählt. Leider ist das Java Collections-Framework - großartig, da es keine Bag-Impls gibt. Dafür muss die Apache Common Collection verwendet werden. Linktext

5
mP.

So rufen Sie die Vorkommen des Objekts direkt aus der Liste ab:

int noOfOccurs = Collections.frequency(animals, "bat");

Überschreiben Sie die equals-Methode in der Object-Klasse wie folgt:

@Override
public boolean equals(Object o){
    Animals e;
    if(!(o instanceof Animals)){
        return false;
    }else{
        e=(Animals)o;
        if(this.type==e.type()){
            return true;
        }
    }
    return false;
}

Animals(int type){
    this.type = type;
}

Rufen Sie die Collections.frequency auf als:

int noOfOccurs = Collections.frequency(animals, new Animals(1));
5
Andrew TR

Einfache Methode zum Ermitteln des Vorkommens eines Zeichenfolgenwerts in einem Array mithilfe von Java 8-Funktionen.

public void checkDuplicateOccurance() {
        List<String> duplicateList = new ArrayList<String>();
        duplicateList.add("Cat");
        duplicateList.add("Dog");
        duplicateList.add("Cat");
        duplicateList.add("cow");
        duplicateList.add("Cow");
        duplicateList.add("Goat");          
        Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString(),Collectors.counting()));
        System.out.println(couterMap);
    }

Ausgabe: {Katze = 2, Ziege = 1, Kuh = 1, Kuh = 1, Hund = 1}

Sie können feststellen, dass "Kuh" und "Kuh" nicht als gleiche Zeichenfolge betrachtet werden. Falls Sie es unter der gleichen Anzahl benötigen, verwenden Sie .toLowerCase (). Das gleiche Snippet finden Sie unten.

Map<String, Long> couterMap = duplicateList.stream().collect(Collectors.groupingBy(e -> e.toString().toLowerCase(),Collectors.counting()));

Ausgabe: {cat = 2, Kuh = 2, Ziege = 1, Hund = 1}

5

Java 8 - eine andere Methode

String searched = "bat";
long n = IntStream.range(0, animals.size())
            .filter(i -> searched.equals(animals.get(i)))
            .count();
2

Wenn Sie Eclipse Collections verwenden, können Sie eine Bag verwenden. Eine MutableBag kann von jeder Implementierung von RichIterable durch Aufruf von toBag() zurückgegeben werden.

MutableList<String> animals = Lists.mutable.with("bat", "owl", "bat", "bat");
MutableBag<String> bag = animals.toBag();
Assert.assertEquals(3, bag.occurrencesOf("bat"));
Assert.assertEquals(1, bag.occurrencesOf("owl"));

Die Implementierung von HashBag in EC wird durch eine MutableObjectIntMap unterstützt.

Hinweis: Ich bin ein Committer für Eclipse Collections.

2
Donald Raab
List<String> list = Arrays.asList("as", "asda", "asd", "urff", "dfkjds", "hfad", "asd", "qadasd", "as", "asda",
        "asd", "urff", "dfkjds", "hfad", "asd", "qadasd" + "as", "asda", "asd", "urff", "dfkjds", "hfad", "asd",
        "qadasd", "as", "asda", "asd", "urff", "dfkjds", "hfad", "asd", "qadasd");

Methode 1:

Set<String> set = new LinkedHashSet<>();
set.addAll(list);

for (String s : set) {

    System.out.println(s + " : " + Collections.frequency(list, s));
}

Methode 2:

int count = 1;
Map<String, Integer> map = new HashMap<>();
Set<String> set1 = new LinkedHashSet<>();
for (String s : list) {
    if (!set1.add(s)) {
        count = map.get(s) + 1;
    }
    map.put(s, count);
    count = 1;

}
System.out.println(map);
1
sabm

Fügen Sie die Elemente der Arrayliste in die HashMap ein, um die Frequenz zu zählen.

1
Shamik

Wenn Sie ein Benutzer von ForEach DSL sind, kann dies mit einer Count-Abfrage erfolgen.

Count<String> query = Count.from(list);
for (Count<Foo> each: query) each.yield = "bat".equals(each.element);
int number = query.result();
0
akuhn
package traversal;

import Java.util.ArrayList;
import Java.util.List;

public class Occurrance {
    static int count;

    public static void main(String[] args) {
        List<String> ls = new ArrayList<String>();
        ls.add("aa");
        ls.add("aa");
        ls.add("bb");
        ls.add("cc");
        ls.add("dd");
        ls.add("ee");
        ls.add("ee");
        ls.add("aa");
        ls.add("aa");

        for (int i = 0; i < ls.size(); i++) {
            if (ls.get(i) == "aa") {
                count = count + 1;
            }
        }
        System.out.println(count);
    }
}

Ausgabe: 4

0
MD EMRUL EMRAN

Machen Sie es also wie gewohnt und rollen Sie Ihre eigene:

Map<String, Integer> instances = new HashMap<String, Integer>();

void add(String name) {
     Integer value = instances.get(name);
     if (value == null) {
        value = new Integer(0);
        instances.put(name, value);
     }
     instances.put(name, value++);
}
0
Mark Renouf
List<String> lst = new ArrayList<String>();

lst.add("Ram");
lst.add("Ram");
lst.add("Shiv");
lst.add("Boss");

Map<String, Integer> mp = new HashMap<String, Integer>();

for (String string : lst) {

    if(mp.keySet().contains(string))
    {
        mp.put(string, mp.get(string)+1);

    }else
    {
        mp.put(string, 1);
    }
}

System.out.println("=mp="+mp);

Ausgabe:

=mp= {Ram=2, Boss=1, Shiv=1}
0
Ramling Muley

Ich wollte diesen Fall nicht schwieriger machen und habe es mit zwei Iteratoren gemacht. Ich habe eine HashMap mit LastName -> FirstName. Und meine Methode sollte Elemente mit dulicate FirstName löschen.

public static void removeTheFirstNameDuplicates(HashMap<String, String> map)
{

    Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
    Iterator<Map.Entry<String, String>> iter2 = map.entrySet().iterator();
    while(iter.hasNext())
    {
        Map.Entry<String, String> pair = iter.next();
        String name = pair.getValue();
        int i = 0;

        while(iter2.hasNext())
        {

            Map.Entry<String, String> nextPair = iter2.next();
            if (nextPair.getValue().equals(name))
                i++;
        }

        if (i > 1)
            iter.remove();

    }

}
0
Map<String,Integer> hm = new HashMap<String, Integer>();
for(String i : animals) {
    Integer j = hm.get(i);
    hm.put(i,(j==null ? 1 : j+1));
}
for(Map.Entry<String, Integer> val : hm.entrySet()) {
    System.out.println(val.getKey()+" occurs : "+val.getValue()+" times");
}
0
fcm45