#java #collections #iterator #maps
#java #Коллекции #итератор #Карты
Вопрос:
В этой задаче мне нужно иметь карту с ключами и значениями строк, чтобы увидеть, соответствуют ли несколько ключей одному и тому же значению. Другими словами, мой метод должен возвращать true, если никакие два ключа не сопоставляются с одним и тем же значением, в то время как false, если это так. Моя попытка приблизиться к этому заключалась в том, чтобы поместить все карты в коллекцию и изучить каждый элемент, чтобы увидеть, есть ли две копии одного и того же значения; однако, похоже, это не работает для меня. Любые предложения будут оценены, спасибо.
Приглашение:
Напишите метод isUnique, который принимает сопоставление строк со строками в качестве параметра и возвращает true, если никакие два ключа не сопоставляются с одним и тем же значением (и false, если любые два или более ключей сопоставляются с одним и тем же значением). Например, вызов вашего метода на следующей карте вернет true:
{Марти = Степп, Стюарт = Реджес, Джессика = Миллер, Аманда = Кэмп, Хэл = Перкинс}
Вызов его на следующей карте вернет false из-за двух сопоставлений для Perkins и Reges:
{Кендрик = Перкинс, Стюарт = Реджес, Джессика = Миллер, Брюс = Реджес, Хэл = Перкинс}
Пустая карта считается уникальной, поэтому ваш метод должен возвращать true, если передана пустая карта.
Моя попытка:
public static boolean isUnique(Map<String, String> input) {
Collection<String> values = input.values(); // stores all the values into a collection
for (String names: values) { // goes through each string to see if any duplicates
Iterator<String> wordList = values.iterator(); // iterates words in values collection
int repeat = 0; // counts number of repeats
// goes through each elem to compare to names
if (wordList.hasNext()) {
if (wordList.next().equals(names)) {
repeat ;
}
}
if (repeat > 1) { // if more than one copy of the value exists = multiple keys to same value
return false; // If multiple copies of same value exists
}
}
return true; // all unique values
}
Ответ №1:
Если я понимаю ваш вопрос, то я бы реализовал ваш метод в общем виде следующим образом —
public static <K, V> boolean isUnique(Map<K, V> input) {
if (input == null || input.isEmpty()) {
return true;
}
Set<V> set = new HashSet<V>();
for (V value : input.values()) {
set.add(value);
}
return set.size() == input.size();
}
Комментарии:
1. Разве мы не помещали бы значения в HashSet вместо ключей, потому что мы пытаемся найти повторяющиеся карты, чтобы от HashSet можно было избавиться?
2. @JackL. Я помещаю повторяющиеся значения в
Set
.input.get(key)
возвращаетV
значение.3. Теперь я вижу это; мой плохой.
Ответ №2:
Одним из решений может быть то, что во время итерации по карте вы можете сохранять значения в наборе строк. Итак, если размер исходной карты и набора одинаков, то нет значения, которое сопоставляется с двумя или более ключами карты.
Что касается реализации, это можно сделать следующим образом:
public boolean checkMap(Map<String, String> map) {
Set<String> set = new HashSet<String>();
for(Entry<String, String> entry:map.entrySet()) {
set.add(entry.getValue);
}
if(map.size == set.size)
return true;
return false;
}
Ответ №3:
Самый короткий способ, который я могу придумать, чтобы сделать это
public static boolean valuesAreUnique(Map<K,V> input) {
Collection<V> values = input.values();
return (new HashSet<V>(values)).size() == values.size();
}
Однако это не самый эффективный способ сделать это, потому что по мере создания набора он будет продолжать добавлять элементы даже после того, как будет найден дубликат. Поэтому, скорее всего, будет работать лучше, если вы выполните следующее, в котором используется возвращаемое значение из add
метода Set
интерфейса.
public static boolean valuesAreUnique(Map<K,V> input) {
Set<V> target = new HashSet<V>();
for (V value: input.values()) {
boolean added = target.add(value);
if (! added) {
return false;
}
}
return true;
}
Комментарии:
1. Это классный способ сделать это. Я не знал, что метод add имеет возвращаемое значение. Поскольку интерфейс списка имеет практически идентичные наборы общих методов, возвращает ли он значение и для списков?
2. Ну, да,
add
метод действительно имеет возвращаемое значение дляList
s, но это не очень полезно, потому что это всегдаtrue
, потому что aList
разрешено содержать дубликаты.
Ответ №4:
Подход Шриканта Какани и Эллиота Фриша верен. Но мы можем сделать это более эффективным, остановив итерацию, как только мы нашли дубликат:
public static boolean isUnique(Map<String, String> input) {
Set<String> uniqueValues = new HashSet<String>();
for (String value : input.values()) {
if (uniqueValues.contains(value)) {
return false;
}
uniqueValues.add(value);
}
return true;
}
Комментарии:
1. Вы можете сделать это еще более эффективным, используя возвращаемое значение from
add
— что в основном делает его таким же, как и вторая часть моего ответа.2. @DavidWallace Правильно, Дэвид. Спасибо. Вашего ответа не было, когда я писал свой.
Ответ №5:
Упражнения из книги специфичны для этой главы, и, насколько я понимаю, ожидается, что в ней будет решение для рассматриваемой темы. Понятно, что существует множество и лучших решений, которые были представлены выше, но данное упражнение охватывает карту, ключи, значения и методы, связанные с ними. Использование приведенного ниже метода прекращается, как только значение используется во второй раз.
public static boolean isUnique(Map<String, String> map){
Map<String, Integer> check = new HashMap<String, Integer>();
for (String v : map.values()){
if (check.containsKey(v)){
return false;
} else {
check.put(v, 1);
}
}
return true;
}