値"foo"
があり、HashMap<String> ftw
がをftw.containsValue("foo")
返すtrue
場合、対応するキーを取得するにはどうすればよいですか?ハッシュマップをループする必要がありますか?それを行う最良の方法は何ですか?
public static final String TIME = "time";
およびproperties.put(TIME, PbActivityJpa_.time);
値"foo"
があり、HashMap<String> ftw
がをftw.containsValue("foo")
返すtrue
場合、対応するキーを取得するにはどうすればよいですか?ハッシュマップをループする必要がありますか?それを行う最良の方法は何ですか?
public static final String TIME = "time";
およびproperties.put(TIME, PbActivityJpa_.time);
回答:
標準のJavaコレクションAPIの代わりにCommonsコレクションライブラリを使用することを選択した場合、これは簡単に実現できます。
コレクションライブラリのBidiMapインターフェースは双方向マップであり、キーを値にマップできます(通常のマップのように)。また、値をキーにマップできるため、双方向でルックアップを実行できます。値のキーの取得は、getKey()メソッドでサポートされています。
ただし、注意点があります。Bidiマップはキーにマップされた複数の値を持つことができないため、データセットにキーと値の間の1:1マッピングがない限り、Bidimapsを使用できません。
更新
JavaコレクションAPIに依存する場合は、マップに値を挿入するときに、キーと値の1対1の関係を確認する必要があります。これは言うより簡単です。
それが確認できたら、entrySet()メソッドを使用して、マップ内のエントリ(マッピング)のセットを取得します。タイプがMap.Entryであるセットを取得したら、エントリを反復処理し、格納された値を期待値と比較して、対応するキーを取得します。
アップデート#2
ジェネリックを使用したBidiマップのサポートは、Google GuavaとリファクタリングされたCommons-Collectionsライブラリにあります(後者はApacheプロジェクトではありません)。Apache Commons Collectionsに欠けている一般的なサポートを指摘してくれたEskoに感謝します。ジェネリックでコレクションを使用すると、コードの保守が容易になります。
データ構造にキーと値の間の多対1マッピングがある場合は、エントリを反復処理し、適切なキーをすべて選択する必要があります。
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
Set<T> keys = new HashSet<T>();
for (Entry<T, E> entry : map.entrySet()) {
if (Objects.equals(value, entry.getValue())) {
keys.add(entry.getKey());
}
}
return keys;
}
以下の場合、1対1の関係には、最初にマッチしたキーを返すことができます。
public static <T, E> T getKeyByValue(Map<T, E> map, E value) {
for (Entry<T, E> entry : map.entrySet()) {
if (Objects.equals(value, entry.getValue())) {
return entry.getKey();
}
}
return null;
}
Java 8の場合:
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
return map.entrySet()
.stream()
.filter(entry -> Objects.equals(entry.getValue(), value))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
また、グアバのユーザーにとっては、BiMapが役立つかもしれません。例えば:
BiMap<Token, Character> tokenToChar =
ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);
o(1)
です。値を繰り返し処理していると、パフォーマンスが低下します。あなたがしたい場合better performance
や持っているone-one
関係を、あなたが使用することができるanother map
場所value is a key
.filter(entry -> entry.getValue().equals(value))
してについての声明としての能力がなされませんでした。さらに、あなたは置き換えることができて.filter(entry ->
Objects.equals
(entry.getValue(), value))
null
.map(entry -> entry.getKey())
.map(Map.Entry::getKey)
public class NewClass1 {
public static void main(String[] args) {
Map<Integer, String> testMap = new HashMap<Integer, String>();
testMap.put(10, "a");
testMap.put(20, "b");
testMap.put(30, "c");
testMap.put(40, "d");
for (Entry<Integer, String> entry : testMap.entrySet()) {
if (entry.getValue().equals("c")) {
System.out.println(entry.getKey());
}
}
}
}
いくつかの追加情報...あなたに役立つかもしれません
ハッシュマップが本当に大きい場合、上記の方法は適切でない場合があります。ハッシュマップに一意のキーから一意の値へのマッピングが含まれている場合、値からキーへのマッピングを含むもう1つのハッシュマップを維持できます。
つまり、2つのハッシュマップを維持する必要があります
1. Key to value
2. Value to key
その場合、2番目のハッシュマップを使用してキーを取得できます。
キー、値のペアとその逆の両方をマップ構造に挿入できます
map.put("theKey", "theValue");
map.put("theValue", "theKey");
map.get( "theValue")を使用すると、 "theKey"が返されます。
これは、一定のマップを作成するための迅速で汚れた方法です。これは、選択したいくつかのデータセットに対してのみ機能します。
独自の実装でマップを装飾する
class MyMap<K,V> extends HashMap<K, V>{
Map<V,K> reverseMap = new HashMap<V,K>();
@Override
public V put(K key, V value) {
// TODO Auto-generated method stub
reverseMap.put(value, key);
return super.put(key, value);
}
public K getKey(V value){
return reverseMap.get(value);
}
}
その値にマップするすべてのキーを見つけるには、を使用して、ハッシュマップのすべてのペアを反復処理しmap.entrySet()
ます。
Java 8の使用:
ftw.forEach((key, value) -> {
if (value.equals("foo")) {
System.out.print(key);
}
});
value=="foo"
これは機能しません。equals
文字列の比較に使用する必要があります。
value
抑留されていない限り真。
独自のコードでマップを作成する場合は、キーと値をマップに一緒に配置してみてください。
public class KeyValue {
public Object key;
public Object value;
public KeyValue(Object key, Object value) { ... }
}
map.put(key, new KeyValue(key, value));
次に、値がある場合は、キーも持っています。
これは最良の解決策だと思います。元のアドレス:Java2s
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] argv) {
Map<String, String> map = new HashMap<String, String>();
map.put("1","one");
map.put("2","two");
map.put("3","three");
map.put("4","four");
System.out.println(getKeyFromValue(map,"three"));
}
// hm is the map you are trying to get value from it
public static Object getKeyFromValue(Map hm, Object value) {
for (Object o : hm.keySet()) {
if (hm.get(o).equals(value)) {
return o;
}
}
return null;
}
}
簡単な使用法:すべてのデータをhasMapに入れ、item = "Automobile"がある場合、hashMapでそのキーを探します。それは良い解決策です。
getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));
恐らくあなたはあなたの地図を反復する必要があるでしょう。私が思いつくことができる最短のもの:
Iterator<Map.Entry<String,String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,String> entry = iter.next();
if (entry.getValue().equals(value_you_look_for)) {
String key_you_look_for = entry.getKey();
}
}
for(int key: hm.keySet()) {
if(hm.get(key).equals(value)) {
System.out.println(key);
}
}
おそらくとにかくこれを行うmap.entrySet()
ので、使用するエントリを反復処理することが最善の方法のようmap.containsValue()
です。
API開発が19未満のAndroid開発の場合、Vitalii Fedorenkoの1対1の関係ソリューションObjects.equals
は、実装されていないため機能しません。簡単な代替案を次に示します。
public <K, V> K getKeyByValue(Map<K, V> map, V value) {
for (Map.Entry<K, V> entry : map.entrySet()) {
if (value.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
以下を使用できます。
public class HashmapKeyExist {
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<String, String>();
hmap.put("1", "Bala");
hmap.put("2", "Test");
Boolean cantain = hmap.containsValue("Bala");
if(hmap.containsKey("2") && hmap.containsValue("Test"))
{
System.out.println("Yes");
}
if(cantain == true)
{
System.out.println("Yes");
}
Set setkeys = hmap.keySet();
Iterator it = setkeys.iterator();
while(it.hasNext())
{
String key = (String) it.next();
if (hmap.get(key).equals("Bala"))
{
System.out.println(key);
}
}
}
}
はい、これらのさまざまな答えが示唆するものに沿って何かを実装しない限り、ハッシュマップをループする必要があります。entrySetをいじるのではなく、keySet()を取得し、そのセットを反復処理して、一致する値を取得する(最初の)キーを保持します。その値に一致するすべてのキーが必要な場合は、明らかにすべてを行う必要があります。
Jonasが示唆するように、これは既にcontainsValueメソッドが実行していることなので、そのテストをすべてスキップして、毎回反復を実行するだけです(または、コンパイラーがすでに冗長性を排除していることを知っています)。
また、他の回答と比較して、リバースマップが次のようになっている場合
Map<Value, Set<Key>>
その機能が必要な場合(それらを別にする)、必要な場合は、一意でないキー->値のマッピングを処理できます。これは、人々が2つのマップを使用してここで提案するソリューションにうまく組み込まれます。
次のコードを使用して、値を使用してキーを取得できます。
ArrayList valuesList = new ArrayList();
Set keySet = initalMap.keySet();
ArrayList keyList = new ArrayList(keySet);
for(int i = 0 ; i < keyList.size() ; i++ ) {
valuesList.add(initalMap.get(keyList.get(i)));
}
Collections.sort(valuesList);
Map finalMap = new TreeMap();
for(int i = 0 ; i < valuesList.size() ; i++ ) {
String value = (String) valuesList.get(i);
for( int j = 0 ; j < keyList.size() ; j++ ) {
if(initalMap.get(keyList.get(j)).equals(value)) {
finalMap.put(keyList.get(j),value);
}
}
}
System.out.println("fianl map ----------------------> " + finalMap);
public static class SmartHashMap <T1 extends Object, T2 extends Object> {
public HashMap<T1, T2> keyValue;
public HashMap<T2, T1> valueKey;
public SmartHashMap(){
this.keyValue = new HashMap<T1, T2>();
this.valueKey = new HashMap<T2, T1>();
}
public void add(T1 key, T2 value){
this.keyValue.put(key, value);
this.valueKey.put(value, key);
}
public T2 getValue(T1 key){
return this.keyValue.get(key);
}
public T1 getKey(T2 value){
return this.valueKey.get(value);
}
}
String
キーと値としてテストしました。を呼び出すと、が鍵となりますが、map.add("1", "2"); map.add("1","3");
呼び出しmap.getKey("2");
て取得できます。"1"
"1"
"3"
getValue("1")
は戻り3
ます。
java8の場合
map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
.forEach(entry -> System.out.println(entry.getKey()));
public static String getKey(Map<String, Integer> mapref, String value) {
String key = "";
for (Map.Entry<String, Integer> map : mapref.entrySet()) {
if (map.getValue().toString().equals(value)) {
key = map.getKey();
}
}
return key;
}
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class ValueKeysMap<K, V> extends HashMap <K,V>{
HashMap<V, Set<K>> ValueKeysMap = new HashMap<V, Set<K>>();
@Override
public boolean containsValue(Object value) {
return ValueKeysMap.containsKey(value);
}
@Override
public V put(K key, V value) {
if (containsValue(value)) {
Set<K> keys = ValueKeysMap.get(value);
keys.add(key);
} else {
Set<K> keys = new HashSet<K>();
keys.add(key);
ValueKeysMap.put(value, keys);
}
return super.put(key, value);
}
@Override
public V remove(Object key) {
V value = super.remove(key);
Set<K> keys = ValueKeysMap.get(value);
keys.remove(key);
if(keys.size() == 0) {
ValueKeysMap.remove(value);
}
return value;
}
public Set<K> getKeys4ThisValue(V value){
Set<K> keys = ValueKeysMap.get(value);
return keys;
}
public boolean valueContainsThisKey(K key, V value){
if (containsValue(value)) {
Set<K> keys = ValueKeysMap.get(value);
return keys.contains(key);
}
return false;
}
/*
* Take care of argument constructor and other api's like putAll
*/
}
/**
* This method gets the Key for the given Value
* @param paramName
* @return
*/
private String getKeyForValueFromMap(String paramName) {
String keyForValue = null;
if(paramName!=null)) {
Set<Entry<String,String>> entrySet = myMap().entrySet();
if(entrySet!=null && entrySet.size>0) {
for(Entry<String,String> entry : entrySet) {
if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) {
keyForValue = entry.getKey();
}
}
}
}
return keyForValue;
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class M{
public static void main(String[] args) {
HashMap<String, List<String>> resultHashMap = new HashMap<String, List<String>>();
Set<String> newKeyList = resultHashMap.keySet();
for (Iterator<String> iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) {
String hashKey = (String) iterator.next();
if (!newKeyList.contains(originalHashMap.get(hashKey))) {
List<String> loArrayList = new ArrayList<String>();
loArrayList.add(hashKey);
resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
} else {
List<String> loArrayList = resultHashMap.get(originalHashMap
.get(hashKey));
loArrayList.add(hashKey);
resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
}
}
System.out.println("Original HashMap : " + originalHashMap);
System.out.println("Result HashMap : " + resultHashMap);
}
}
薄いラッパーを使用:HMap
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class HMap<K, V> {
private final Map<K, Map<K, V>> map;
public HMap() {
map = new HashMap<K, Map<K, V>>();
}
public HMap(final int initialCapacity) {
map = new HashMap<K, Map<K, V>>(initialCapacity);
}
public boolean containsKey(final Object key) {
return map.containsKey(key);
}
public V get(final Object key) {
final Map<K, V> entry = map.get(key);
if (entry != null)
return entry.values().iterator().next();
return null;
}
public K getKey(final Object key) {
final Map<K, V> entry = map.get(key);
if (entry != null)
return entry.keySet().iterator().next();
return null;
}
public V put(final K key, final V value) {
final Map<K, V> entry = map
.put(key, Collections.singletonMap(key, value));
if (entry != null)
return entry.values().iterator().next();
return null;
}
}
私の2セント。配列のキーを取得して、配列をループ処理できます。これは、マップがかなり大きい場合、このコードブロックのパフォーマンスに影響します。この場合、最初に配列内のキーを取得しますが、時間がかかり、その後ループします。それ以外の場合は、小さいマップの場合は問題ありません。
String[] keys = yourMap.keySet().toArray(new String[0]);
for(int i = 0 ; i < keys.length ; i++){
//This is your key
String key = keys[i];
//This is your value
yourMap.get(key)
}
私が思うのkeySet()が値にマッピングするキーを見つけ、そしてより良いコーディングスタイル持っているだけでなくかもしれのentrySetを() 。
例:
HashMap マップ、ArrayList res、すべてのキーマッピングを検索する値、そしてresにキーを格納するとします。
以下のコードを書くことができます:
for (int key : map.keySet()) {
if (map.get(key) == value) {
res.add(key);
}
}
以下のentrySet()を使用するのではなく、
for (Map.Entry s : map.entrySet()) {
if ((int)s.getValue() == value) {
res.add((int)s.getKey());
}
}
それが役に立てば幸い :)
map.get(key) == value
参照を比較しているので、オブジェクトの等価性をチェックするときはお勧めできません。オブジェクトの等価性は常に使用する必要があります.equals()
これは質問に直接答えるものではありませんが、関連しています。
この方法では、作成/反復を続ける必要はありません。リバースマップを一度作成して、必要なものを取得します。
/**
* Both key and value types must define equals() and hashCode() for this to work.
* This takes into account that all keys are unique but all values may not be.
*
* @param map
* @param <K>
* @param <V>
* @return
*/
public static <K, V> Map<V, List<K>> reverseMap(Map<K,V> map) {
if(map == null) return null;
Map<V, List<K>> reverseMap = new ArrayMap<>();
for(Map.Entry<K,V> entry : map.entrySet()) {
appendValueToMapList(reverseMap, entry.getValue(), entry.getKey());
}
return reverseMap;
}
/**
* Takes into account that the list may already have values.
*
* @param map
* @param key
* @param value
* @param <K>
* @param <V>
* @return
*/
public static <K, V> Map<K, List<V>> appendValueToMapList(Map<K, List<V>> map, K key, V value) {
if(map == null || key == null || value == null) return map;
List<V> list = map.get(key);
if(list == null) {
List<V> newList = new ArrayList<>();
newList.add(value);
map.put(key, newList);
}
else {
list.add(value);
}
return map;
}
値からキーを取得する場合は、bidimap(双方向マップ)を使用するのが最適です。値からキーをO(1)時間で取得できます。
ただし、これの欠点は、一意のキーセットと値セットしか使用できないことです。
javaにはTableというデータ構造があります。これは、次のようなマップのマップにすぎません。
テーブル<A、B、C> ==マップ<A、マップ<B、C>>
ここではmap<B,C>
、クエリを実行して取得できます。また、クエリT.row(a);
を実行して取得map<A,C>
することもできます。T.column(b);
特別なケースでは、定数としてCを挿入します。
したがって、<a1、b1、1> <a2、b2、1>、...
したがって、T.row(a1)で見つかった場合--->マップを返します->キーセットを取得この返されたマップ。
キー値を見つける必要がある場合、T.column(b2)->はmap of-を返します->返されたマップのキーセットを取得します。
前のケースに対する利点: