JavaにHashMap<String, Integer>
があるとします。
見つかった文字列が存在するたびに、文字列キーの整数値を更新(増分)するにはどうすればよいですか。
ペアを削除して再入力することもできますが、オーバーヘッドが問題になります。
別の方法は、新しいペアを置くだけで、古いペアを置き換えることです。
後者の場合、挿入しようとしている新しいキーとハッシュコードが衝突した場合はどうなりますか?ハッシュテーブルの正しい振る舞いは、それに別の場所を割り当てるか、現在のバケットの中でそれからリストを作ることです。
map.put(key, map.get(key) + 1);
大丈夫です。既存のマッピングの値が更新されます。これはオートボクシングを使用していることに注意してください。
computeIfPresent
メソッドを使用して、それにマッピング関数を指定することができます。マッピング関数は、既存の値に基づいて新しい値を計算するために呼び出されます。
例えば、
Map<String, Integer> words = new HashMap<>();
words.put("hello", 3);
words.put("world", 4);
words.computeIfPresent("hello", (k, v) -> v + 1);
System.out.println(words.get("hello"));
代わりに、merge
メソッドを使用することもできます。ここで、1はデフォルト値で、関数は既存の値を1ずつ増やします。
words.merge("hello", 1, Integer::sum);
さらに、putIfAbsent
、getOrDefault
、forEach
など、他にもたくさんの便利な方法があります。
hashmap.put(key, hashmap.get(key) + 1);
メソッドput
は replace を既存のキーの値とし、存在しない場合はそれを作成します。
簡略化された Java 8 way:
map.put(key, map.getOrDefault(key, 0) + 1);
これは、キーの値を取得するHashMapのメソッドを使用しますが、キーを取得できない場合は、指定されたデフォルト値(この場合は「0」)を返します。
これはコアJava内でサポートされています: HashMap <K、V> getOrDefault(オブジェクトキー、V defaultValue)
Integer
を AtomicInteger
に置き換え、その上でincrementAndGet
/getAndIncrement
メソッドのいずれかを呼び出します。
別の方法はincrement()
メソッドを持つあなた自身のint
クラスでMutableInteger
をラップすることです、あなたはまだ解決するべきスレッドセーフティの懸念があるだけです。
@ Matthewのソリューションは最も簡単で、ほとんどの場合十分に機能します。
高性能が必要な場合は、AtomicIntegerが@BalusCより優れたソリューションです。
ただし、より高速な解決策(スレッドの安全性が問題にならない場合)は TObjectIntHashMap を使用することです。これはincrement(key)メソッドを提供し、AtomicIntegersを作成するよりもプリミティブを使用しオブジェクトを少なくします。例えば.
TObjectIntHashMap<String> map = new TObjectIntHashMap<String>()
map.increment("aaa");
1行ソリューション
map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);
以下のようにインクリメントできますが、存在を確認してNullPointerExceptionがスローされないようにする必要があります。
if(!map.containsKey(key)) {
p.put(key,1);
}
else {
p.put(key, map.getKey()+1);
}
ハッシュは存在しますか(値が0である)、それとも最初の増分でマップに「入れられる」か。最初のインクリメントで "put"されている場合、コードは次のようになります。
if (hashmap.containsKey(key)) {
hashmap.put(key, hashmap.get(key)+1);
} else {
hashmap.put(key,1);
}
それは少し遅くなるかもしれませんが、ここに私の2セントです。
Java 8を使用している場合は、 computeIfPresent メソッドを使用できます。指定されたキーの値が存在し、nullでない場合は、キーとその現在のマップ値を指定して新しいマッピングを計算しようとします。
final Map<String,Integer> map1 = new HashMap<>();
map1.put("A",0);
map1.put("B",0);
map1.computeIfPresent("B",(k,v)->v+1); //[A=0, B=1]
キーを置くために別のメソッド putIfAbsent を利用することもできます。指定されたキーがまだ値に関連付けられていない(またはnullにマッピングされている)場合、このメソッドはそれを指定された値に関連付けてnullを返し、そうでない場合は現在の値を返します。
マップがスレッド間で共有されている場合は、ConcurrentHashMap
および AtomicInteger を使用できます。ドキュメントから:
AtomicInteger
はアトミックに更新できるint値です。 AtomicIntegerは、アトミックインクリメントカウンタなどのアプリケーションで使用され、Integerの代わりには使用できません。ただし、このクラスはNumberを拡張して、数値ベースのクラスを扱うツールやユーティリティによる統一的なアクセスを可能にします。
私達は示されているようにそれらを使用することができます:
final Map<String,AtomicInteger> map2 = new ConcurrentHashMap<>();
map2.putIfAbsent("A",new AtomicInteger(0));
map2.putIfAbsent("B",new AtomicInteger(0)); //[A=0, B=0]
map2.get("B").incrementAndGet(); //[A=0, B=1]
注意すべき点の1つは、キーget
の値を取得するためにB
を呼び出してから、その値に対してもちろんAtomicInteger
であるincrementAndGet()
を呼び出すことです。メソッドputIfAbsent
がすでに存在する場合はキーの値を返すので、これを最適化できます。
map2.putIfAbsent("B",new AtomicInteger(0)).incrementAndGet();//[A=0, B=2]
ちなみに AtomicLong を使用する予定がある場合は、競合が激しい場合のドキュメントのとおり、 LongAdder のスループットが大幅に高くなりますが、スペースの消費は増えます。これもチェックしてください question 。
NullPointerExceptionを使わないでよりきれいな解決策は:
map.replace(key, map.get(key) + 1);
インデックスを増やすにはfor
ループを使います。
for (int i =0; i<5; i++){
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("beer", 100);
int beer = map.get("beer")+i;
System.out.println("beer " + beer);
System.out ....
}
この質問に対する誤解を招くような答えがあります。キーが存在する場合、Hashtableのputメソッドが既存の値を置き換えることを意味します。これはHashtableではなくHashMapに当てはまります。 HashMapのJavadocを参照してください http://docs.Oracle.com/javase/7/docs/api/Java/util/HashMap.html#put%28K,%20V%29
評判が悪いためにいくつかの回答にコメントすることはできないので、私は自分が適用した解決策を投稿します。
for(String key : someArray)
{
if(hashMap.containsKey(key)//will check if a particular key exist or not
{
hashMap.put(hashMap.get(key),value+1);// increment the value by 1 to an already existing key
}
else
{
hashMap.put(key,value);// make a new entry into the hashmap
}
}
Java 8組み込み関数 'computeIfPresent'を使用
例:
public class ExampleToUpdateMapValue {
public static void main(String[] args) {
Map<String,String> bookAuthors = new TreeMap<>();
bookAuthors.put("Genesis","Moses");
bookAuthors.put("Joshua","Joshua");
bookAuthors.put("Judges","Samuel");
System.out.println("---------------------Before----------------------");
bookAuthors.entrySet().stream().forEach(System.out::println);
// To update the existing value using Java 8
bookAuthors.computeIfPresent("Judges", (k,v) -> v = "Samuel/Nathan/Gad");
System.out.println("---------------------After----------------------");
bookAuthors.entrySet().stream().forEach(System.out::println);
}
}
試してください:
HashMap hm=new HashMap<String ,Double >();
注意:
String->give the new value; //THIS IS THE KEY
else
Double->pass new value; //THIS IS THE VALUE
ハッシュマップのキーまたは値を変更することはできますが、両方を同時に変更することはできません。
Integer i = map.get(key);
if(i == null)
i = (aValue)
map.put(key, i + 1);
または
Integer i = map.get(key);
map.put(key, i == null ? newValue : i + 1);
整数はプリミティブデータ型 http://cs.fit.edu/~ryan/Java/language/Java-data.html なので、取り出す必要があります。何らかの処理を行ってから元に戻す必要があります。 Primitiveデータ型ではない値がある場合は、取り出して処理するだけでよく、ハッシュマップに戻す必要はありません。