путаница в методе HashMap содержит значение - PullRequest
1 голос
/ 28 июня 2011

Я пытаюсь найти упрощенную версию моего метода, и я хотел бы знать, если у вас есть лучшее мнение.

В основном у меня есть HashMap, который хранит значение ключа как String-String []

Я хотел бы иметь метод, который определяет, содержит ли новое вставленное значение String [] значение String, которое уже присутствует в уже сохраненном значении String [].

Что у меня естьнаписано "и, видимо, работает нормально" следующий метод:

static Map<String,String[]> myMap=new HashMap<String,String[]>();

    public static boolean kijkContains(String[] syn){

for(String s:myMap.keySet()){

    String[]temp=myMap.get(s);

    for(int i=0; i<temp.length; i++){

        for(int k=0; k<syn.length; k++){

            if(temp[i].equals(syn[k])){

                return true;
            }
        }
    }
  }
return false;
}

Мои сомнения касаются количества циклов, это, очевидно, метод с высоким потреблением памяти, и мне было интересно, если вы можете думать о каких-либоЛучшая версия.

Я пытался использовать метод MapV containsValue (), но так как этот метод видит в качестве значения String [] вместо чтения массива, я не могу использовать его в качестве компаратора.

Ответы [ 6 ]

3 голосов
/ 28 июня 2011

С имеющейся у вас структурой данных нет лучшего способа, чем зацикливаться на всех этих значениях (по крайней мере, вы пробиваетесь рано при первом попадании).

Если производительность действительно становится проблемой, выможет захотеть сохранить вторую структуру данных, чтобы индексировать то, что уже есть.Если вам нужно только знать, находится ли данная Строка (глубоко) на Карте (но не где), возможно, сработает HashSet<String>.

Это компромисс памяти: добавленная структура индекса заняла бы дополнительное пространство.(Кстати, то, что вы делаете сейчас, не использует никакого пространства в дополнение к тому, что уже занимает карта, вы просто перебираете массивы по ссылке, никаких дополнительных копий не делается).

2 голосов
/ 28 июня 2011

Ваш код не использует особенно большой объем памяти, поскольку вы не создаете копии каких-либо String[] (вы только копируете ссылки на них, что очень дешево).

Однако , вам нужно перебрать все значения в HashMap, что делает это O (n) (или просто говоря: медленно).

Если это относительно редкая операция, то это, вероятно, приемлемо, и я бы не стал беспокоиться об этом.

Если вставка является распространенной операцией, то вам определенно следует подумать о лучшей структуре данных для этого (вам нужно больше рассказать нам о фактическом сценарии использования, чтобы мы могли сделать хорошие предложения здесь).

0 голосов
/ 28 июня 2011

Итак, вы хотите, чтобы каждая строка в значении HashMap была уникальной. Я думаю, что если вы используете HashSet вместо String [] для значения Map, это будет работать.

import java.util. *;

открытый класс TestHashMap { public static void main (Строковые аргументы []) {

System.out.println("Hashmap Test");
HashMap<String, HashSet> myMap = new HashMap<String, HashSet>();

HashSet<String> s1 = new HashSet<String>();
s1.add("one");
s1.add("two");
s1.add("three");

myMap.put("1", s1);
System.out.println("Value for key 1" + myMap.get("1"));

} }

Надеюсь, ты так хотел.

0 голосов
/ 28 июня 2011

Вы можете уменьшить сложность времени, скопировав массив syn в HashSet.Тогда вместо того, чтобы перебирать syn снова и снова, вы можете использовать метод HashSet#contains, который является O (1):

public static boolean kijkContains(String[] syn){
  if (syn == null || syn.length == 0) return false; // that was missing
  Set<String> input = new HashSet<String>();
  for (String s:syn)
    input.add(s);         // will remove duplicates, another perfo improvement

  for(String key:myMap.keySet()){
    for(String s:myMap.get(key)){  // we don't need the loop variable
      if (input.contains(s)) {
        return true;
      }
    }
  }
  return false;
}

сложность была O(i*j*k), и яуменьшил его до O(i*j+k) (размер i - это карта, j - средний размер массивов значений и k - размер массива syn)

0 голосов
/ 28 июня 2011

Вы можете использовать метод containsValue (), чтобы сделать это. Вам не нужно повторять бросать весь HashMap.

http://msdn.microsoft.com/en-us/library/aa989118%28v=vs.80%29.aspx

http://www.javadocexamples.com/java/util/HashMap/containsValue%28Object%20value%29.html

0 голосов
/ 28 июня 2011

Ну, я не знал другого способа, кроме циклического перебора значений, но я бы предложил более простой код для этого:

Map<String, String[]> map = new HashMap<String, String[]>();
for (String[] strings : map.values()) {
    ArrayUtils.contains(strings, "foo");
}

ArrayUtils - это вспомогательный класс из Apache Commons, но конечноВы также можете циклически перебирать массив строк и каждый раз вызывать equals.Будьте внимательны, чтобы учитывать регистр символов.

Map<String, String[]> map = new HashMap<String, String[]>();
for (String[] strings : map.values()) {
    for (String string : strings) {
        if (string.equals("foo")) {
            return true;
        }
    }
}
...