216

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

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

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

Google の CollectionMultisetには、要素の総出現回数を返す API があることがわかりました。ただし、これは JDK 1.5 とのみ互換性があります。当社の製品は現在JDK 1.6にあるため、使用できません。

4

25 に答える 25

398

Collections の static frequency-method がここで役立つと確信しています。

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

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

于 2010-03-17T03:35:24.680 に答える
138

Java 8 では:

Map<String, Long> counts =
    list.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
于 2014-11-29T19:18:39.743 に答える
24

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

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

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

以下は、これがどのように記述されるかについての非常に基本的なサンプルです。これはサンプルにすぎません。本番用のリストはさらに複雑になります。

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

ここで適用される OO の原則: 継承、ポリモーフィズム、抽象化、カプセル化。

于 2009-02-03T22:50:28.020 に答える
14

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

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); }
}
于 2009-02-03T03:35:29.363 に答える
10

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

于 2009-02-03T03:33:26.140 に答える
9

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

出力: {猫=2、ヤギ=1、牛=1、牛=1、犬=1}

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

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

出力: {猫=2、牛=2、ヤギ=1、犬=1}

于 2017-11-14T10:20:32.357 に答える
8

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

私はどこか間違っていますか?

于 2009-02-03T03:42:23.110 に答える
6

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

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();
}
于 2009-02-03T22:07:52.693 に答える
5

必要なのは Bag です。これはセットのようなものですが、出現回数もカウントします。残念ながら、Java Collections フレームワーク - Bag impl がないので素晴らしいです。そのためには、Apache Common Collectionリンク テキストを使用する必要があります。

于 2009-02-03T03:35:30.893 に答える
5

それを達成するには、いくつかの方法があります。

単一要素の出現回数を返すメソッド:

収集頻度

Collections.frequency(animals, "bat");

Java ストリーム:

フィルター

animals.stream().filter("bat"::equals).count();

リストを考えただけの繰り返し

public static long manually(Collection<?> c, Object o){
    int count = 0;
    for(Object e : c)
        if(e.equals(o))
            count++;
    return count;
}

頻度のマップを作成するメソッド:

Collectors.groupingBy

Map<String, Long> counts = 
       animals.stream()
              .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

マージ

Map<String, Long> map = new HashMap<>();
c.forEach(e -> map.merge(e, 1L, Long::sum));

手動で

Map<String, Integer> mp = new HashMap<>();
        animals.forEach(animal -> mp.compute(animal, (k, v) -> (v == null) ? 1 : v + 1));

すべてのメソッドを使用した実行例:

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Frequency {

    public static int frequency(Collection<?> c, Object o){
        return Collections.frequency(c, o);
    }

    public static long filter(Collection<?> c, Object o){
        return c.stream().filter(o::equals).count();
    }

    public static long manually(Collection<?> c, Object o){
        int count = 0;
        for(Object e : c)
            if(e.equals(o))
                count++;
        return count;
    }

    public static Map<?, Long> mapGroupBy(Collection<?> c){
        return c.stream()
                .collect(Collectors.groupingBy(Function.identity() , Collectors.counting()));
    }

    public static Map<Object, Long> mapMerge(Collection<?> c){
        Map<Object, Long> map = new HashMap<>();
        c.forEach(e -> map.merge(e, 1L, Long::sum));
        return map;
    }

    public static Map<Object, Long> manualMap(Collection<?> c){
        Map<Object, Long> map = new HashMap<>();
        c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
        return map;
    }


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

        System.out.println(frequency(animals, "bat"));
        System.out.println(filter(animals,"bat"));
        System.out.println(manually(animals,"bat"));
        mapGroupBy(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
        mapMerge(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
        manualMap(animals).forEach((k, v) -> System.out.println(k + " -> "+v));
    }
}

メソッド名は、それらのメソッドが何をしているかを反映している必要がありますが、代わりに使用されているアプローチを反映するために名前を使用しました (現在のコンテキストでは問題ないことを前提としています)。

于 2021-02-22T18:40:45.430 に答える
2

Eclipse Collectionsを使用する場合は、Bag. を呼び出すことによりMutableBag、 の任意の実装からAを返すことができます。RichIterabletoBag()

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

Eclipse コレクションでのHashBag実装は、MutableObjectIntMap.

注:私は Eclipse コレクションのコミッターです。

于 2015-01-28T22:52:44.263 に答える
1

だから、昔ながらの方法でそれを行い、独自のロールを作成します。

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++);
}
于 2009-02-03T03:36:25.010 に答える
1

頻度をカウントするために、arraylist の要素を hashMap に入れます。

于 2009-02-03T04:06:23.593 に答える
1
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

于 2019-06-20T03:45:03.487 に答える
1

Java 8 - 別の方法

String searched = "bat";
long n = IntStream.range(0, animals.size())
            .filter(i -> searched.equals(animals.get(i)))
            .count();
于 2016-02-04T10:58:17.093 に答える
0

このケースをこれ以上難しくしたくなかったので、2 つのイテレータを使用して作成しました。LastName -> FirstName の HashMap があります。そして、私のメソッドは、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();

    }

}
于 2016-08-31T16:11:10.257 に答える
0

あなたが私のForEach DSLのユーザーであれば、Countクエリで実行できます。

Count<String> query = Count.from(list);
for (Count<Foo> each: query) each.yield = "bat".equals(each.element);
int number = query.result();
于 2009-03-01T19:22:06.287 に答える
0
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}
于 2014-10-08T09:49:25.260 に答える