web-dev-qa-db-ja.com

リスト内の要素の出現回数を数える方法

次のように、JavaのCollectionクラスであるArrayListがあります。

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

ご覧のとおり、animalsArrayListは、3つのbat要素と1つのowl要素で構成されています。 Collectionフレームワークに、batの出現回数を返すAPIがあるのか​​、または出現回数を決定する別の方法があるのか​​疑問に思っていました。

GoogleのコレクションMultisetには、要素の合計出現数を返すAPIがあることがわかりました。ただし、これはJDK 1.5とのみ互換性があります。当社の製品は現在JDK 1.6に含まれているため、使用できません。

155
MM.

コレクションの静的周波数メソッドがここで役立つと確信しています。

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

とにかくそうするのです。私はこれがjdk 1.6であると確信しています。

300
Lars Andren

Java 8の場合:

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

これは、 Effective Java bookで説明されているように、「 インターフェースでオブジェクトを参照 」が重要である理由を示しています。

実装にコーディングして、たとえばコード内の50箇所でArrayListを使用する場合、項目をカウントする適切な「リスト」実装を見つけたら、それらの50箇所すべてを変更する必要があります。あなたのコードを壊します(あなただけがそれを使用する場合、大したことはありませんが、他の誰かが使用する場合、あなたのコードも壊します)

インターフェイスにプログラミングすることにより、これらの50の場所を変更せずに、ArrayListから "CountItemsList"(たとえば)または他のクラスに実装を置き換えることができます。

以下は、これをどのように書くことができるかについての非常に基本的なサンプルです。これは単なるサンプルであり、プロダクション準備リストはmuchより複雑になります。

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

ここで適用されるオブジェクト指向の原則:継承、ポリモーフィズム、抽象化、カプセル化。

22
OscarRyz

申し訳ありませんが、それを実行できる簡単なメソッド呼び出しはありません。ただし、マップを作成して頻度をカウントするだけです。

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

実際、Collectionsクラスには次の静的メソッドがあります:frequency(Collection c、Object o)これは、検索対象の要素の出現回数を返します。ところで、これは完璧に機能します。

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

Javaには、それを行うためのネイティブメソッドはありません。ただし、Apache Commons-Collectionsの IterableUtils#countMatches() を使用して実行できます。

9
Kevin

JDK 1.6でそのGoogleのCollection APIを使用できないのはなぜでしょうか。それはそう言いますか?下位バージョン用に構築されているため、互換性の問題はないはずです。 1.6用にビルドされ、1.5を実行している場合、ケースは異なります。

どこか間違ってる?

8
Adeel Ansari

もう少し効率的なアプローチは

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

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

出力:{Cat = 2、Goat = 1、Cow = 1、cow = 1、Dog = 1}

「牛」と牛は同じ文字列とは見なされないことに気付くことができます。同じカウントで必要な場合は、.toLowerCase()を使用します。同じために以下のスニペットを見つけてください。

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

出力:{cat = 2、cow = 2、goat = 1、dog = 1}

6

代替​​Java 8Streamsを使用したソリューション:

long count = animals.stream().filter(animal -> "bat".equals(animal)).count();
6
Cristina

欲しいのはバッグです-これはセットのようなものですが、発生回数もカウントします。残念ながらJavaコレクションフレームワーク-Bag implがないので素晴らしいです。そのためには、Apache Common Collectionを使用する必要があります link text

5
mP.

リストからオブジェクトのオカレンスを直接取得するには:

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

リスト内のオブジェクトコレクションの出現を取得するには、Objectクラスのequalsメソッドを次のようにオーバーライドします。

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

Collections.frequencyを次のように呼び出します。

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

Java 8-別のメソッド

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

方法1:

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

for (String s : set) {

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

方法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);
2
sabm

Eclipse Collections を使用する場合、Bagを使用できます。 MutableBagは、 RichIterable の任意の実装から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"));

ECのHashBag実装は、MutableObjectIntMapによってサポートされています。

注:私はEclipse Collectionsのコミッターです。

2
Donald Raab

配列リストの要素をhashMapに入れて、頻度をカウントします。

1
Shamik

あなたが私の ForEach DSL のユーザーであれば、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);
    }
}

出力:4

0
MD EMRUL EMRAN

それで、昔ながらの方法でそれをして、あなた自身を転がしてください:

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

出力:

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

私はこのケースをより難しくしたくなく、LastName-> FirstNameのHashMapを持つ2つのイテレーターでそれを作りました。そして、私のメソッドは重複した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
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