web-dev-qa-db-fra.com

Comment compter le nombre d'occurrences d'un élément dans une liste

J'ai une ArrayList, une classe Collection de Java, comme suit:

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

Comme vous pouvez le constater, la variable animalsArrayList se compose de 3 éléments bat et d'un élément owl. Je me demandais s'il existe une API dans la structure Collection qui renvoie le nombre d'occurrences bat ou s'il existe un autre moyen de déterminer le nombre d'occurrences.

J'ai découvert que Collection Multiset de Google dispose d'une API qui renvoie le nombre total d'occurrences d'un élément. Mais cela n’est compatible qu’avec JDK 1.5. Notre produit est actuellement en JDK 1.6, je ne peux donc pas l'utiliser.

150
MM.

Je suis à peu près sûr que la méthode de la fréquence statique dans Collections serait utile ici:

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

C'est comme ça que je le ferais quand même. Je suis à peu près sûr que c'est jdk 1.6 directement.

292
Lars Andren

En Java 8:

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

Cela montre pourquoi il est important de " Faire référence aux objets par leurs interfaces " comme décrit dans Effective Java book.

Si vous codez pour l'implémentation et utilisez ArrayList dans, disons, 50 emplacements dans votre code, lorsque vous trouvez une bonne implémentation "Liste" qui compte les éléments, vous devrez modifier ces 50 emplacements, et probablement casser votre code (s'il est seulement utilisé par vous, ce n'est pas grave, mais s'il est utilisé par quelqu'un d'autre, vous casserez aussi son code) 

En programmant sur l'interface, vous pouvez laisser ces 50 emplacements inchangés et remplacer l'implémentation d'ArrayList par "CountItemsList" (par exemple) ou par une autre classe.

Vous trouverez ci-dessous un exemple très simple expliquant comment cela pourrait être écrit. Ceci est seulement un exemple, une liste prête pour la production serait beaucoup plus compliquée.

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" ));
    }
}

Principes OO appliqués ici: héritage, polymorphisme, abstraction, encapsulation.

21
OscarRyz

En fait, la classe Collections a une méthode statique appelée: frequency (Collection c, Object o) qui renvoie le nombre d’occurrences de l’élément recherché, mais qui fonctionnera parfaitement pour vous: 

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

Désolé, il n'y a pas d'appel de méthode simple qui puisse le faire. Tout ce que vous avez à faire est de créer une carte et de compter sa fréquence.

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

Il n'y a pas de méthode native en Java pour le faire pour vous. Cependant, vous pouvez utiliser IterableUtils # countMatches () d'Apache Commons-Collections pour le faire à votre place.

9
Kevin

Je me demande pourquoi vous ne pouvez pas utiliser cette API de collection de Google avec JDK 1.6. Cela dit-il? Je pense que vous pouvez, il ne devrait pas y avoir de problèmes de compatibilité, car il est construit pour une version plus basse. Le cas aurait été différent si cela avait été construit pour 1.6 et que vous exécutiez 1.5.

Est-ce que je me trompe quelque part?

8
Adeel Ansari

Une approche légèrement plus efficace pourrait être

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 solution utilisant Streams :

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

Ce que vous voulez, c'est un sac - qui ressemble à un ensemble, mais compte également le nombre d'occurrences. Malheureusement, le framework Java Collections est génial, car il n’a pas d’implication Bag. Pour cela, il faut utiliser Apache Common Collection link text

5
mP.

Pour obtenir directement les occurrences de l'objet de la liste:

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

Pour obtenir l'occurrence de la collection Object dans la liste, substituez la méthode equals dans la classe Object comme suit:

@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;
}

Appelez Collections.frequency en tant que:

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

Simple moyen de rechercher l'occurrence d'une valeur de chaîne dans un tableau à l'aide des fonctionnalités de Java 8.

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);
    }

Sortie: {Cat = 2, Chèvre = 1, Vache = 1, Vache = 1, Chien = 1}

Vous pouvez remarquer que "Vache" et que la vache ne sont pas considérées comme une même chaîne. Si vous en aviez besoin sous le même compte, utilisez .toLowerCase (). Veuillez trouver l'extrait ci-dessous pour la même chose.

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

Sortie: {cat = 2, vache = 2, chèvre = 1, chien = 1}

5
Eswaran Venkatesan

Java 8 - autre méthode

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

Si vous utilisez Collections Eclipse , vous pouvez utiliser une variable Bag. Une MutableBag peut être renvoyée depuis n'importe quelle implémentation de RichIterable en appelant toBag().

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"));

L'implémentation HashBag dans EC est soutenue par un MutableObjectIntMap.

Note: Je suis un partisan des collections Eclipse.

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");

Méthode 1:

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

for (String s : set) {

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

Méthode 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

Placez les éléments de l'arraylist dans la table de hachage pour compter la fréquence.

1
Shamik

Si vous êtes utilisateur de mon ForEach DSL , vous pouvez le faire avec une requête Count.

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);
    }
}

Sortie: 4

0
MD EMRUL EMRAN

Alors faites-le à l'ancienne et faites le vôtre:

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);

Sortie:

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

Je ne voulais pas rendre cette affaire plus difficile et je l'ai fait avec deux itérateurs J'ai un HashMap avec LastName -> FirstName. Et ma méthode devrait supprimer les éléments avec dulicate FirstName.

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
Alexander Shapkin
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