Используя два (или больше) возражает как ключ HashMap

Я хочу, чтобы эта функция работала со всеми положительными 64-битными целыми числами со знаком

Math.sqrt() работает с двойными числами в качестве входных параметров, поэтому вы не получите точных результатов для целых чисел большего размера чем 2 ^ 53 .

12
задан Gambler 27 July 2009 в 19:16
поделиться

7 ответов

Ваш ключ должен реализовывать hashCode и равно. Если это SortedMap , он также должен реализовывать интерфейс Comparable

public class MyKey implements Comparable<MyKey>
{
private Integer i;
private String s;
public MyKey(Integer i,String s)
{
this.i=i;
this.s=s;
}

public Integer getI() { return i;}
public String getS() { return s;}

@Override
public int hashcode()
{
return i.hashcode()+31*s.hashcode();
}

@Override
public boolean equals(Object o)
{
if(o==this) return true;
if(o==null || !(o instanceof MyKey)) return false;
MyKey cp= MyKey.class.cast(o);
return i.equals(cp.i) && s.equals(cp.s);
    }

   public int compareTo(MyKey cp)
     {
     if(cp==this) return 0;
     int i= i.compareTo(cp.i);
     if(i!=0) return i;
     return s.compareTo(cp.s);
     }


 @Override
    public String toString()
       {
       return "("+i+";"+s+")";
       }

    }

public Map<MyKey,String> map= new HashMap<MyKey,String>();
map.put(new MyKey(1,"Hello"),"world");
14
ответ дан 2 December 2019 в 04:25
поделиться

Я обычно использую список

map.put(Arrays.asList(keyClass, keyString), value)
10
ответ дан 2 December 2019 в 04:25
поделиться

В Apache Commons Collections есть карта с несколькими ключами, которая может помочь вам:

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/ commons / collections4 / keyvalue / MultiKey.html

Похоже, он будет обрабатывать до 5 «ключей».

3
ответ дан 2 December 2019 в 04:25
поделиться

Самый простой способ, который я знаю, - это создать класс-оболочку и переопределить хэш-карту и равенство. Например:

public class KeyClass {

    private String element1;
    private String element2;

    //boilerplate code here

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof KeyClass) {
            return element1.equals(((KeyClass)obj).element1) &&
                element2.equals(((KeyClass)obj).element2);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (element1 + element2).hashcode();
    }
}

Конечно, я бы порекомендовал использовать StringBuilder и что-то еще, но таким образом вы переопределите равенство и хэш-код, тем самым позволяя проверку хэша и равенства для ваших нескольких ключей.

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

4
ответ дан 2 December 2019 в 04:25
поделиться

Есть несколько мест, где люди предлагают создать "Ключевой" класс, содержащий остальные, я полностью согласен. Просто подумал, что добавлю полезный совет.

Если вы используете eclipse или netbeans, у них есть хороший вариант - вы можете указать Eclipse создать методы equals и hashcode на основе одного или нескольких членов. Итак, вы просто выбираете член (или членов), который хотите получить, и NB создает большую часть кода, который вам нужно написать для вас.

Конечно, когда я просто хочу получить по одному объекту, я часто просто делегирую методы hashcode и equals для этого объекта (делегирование equals может быть проблематичным, потому что это будет означать, что один из ваших классов «Key Holder» будет равен объекту, который является его ключом, но это довольно легко исправить (и обычно не влияет в любом случае)

так что из моей головы:

class KeyHolder {
    public final String key;
    public final Object storeMe;

    public KeyHolder(String key, Object storeMe) {
        this.key=key;
        this.storeMe=storeMe;
    }

    public equals(Object o) {
        return (o instanceof KeyHolder && ((KeyHolder)o).key.equals(key));
    }

    public hashcode() {
        return key.hashCode();
    }
}

Вот и все, и eclipse сделает последние два за вас, если вы попросите.

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

0
ответ дан 2 December 2019 в 04:25
поделиться

В C # используйте делегаты для передачи операций « <» и «> » в код, выполняющий эту работу.

Пример C # :

public delegate bool BooleanOperatorDelegate(int a, int b)

class OperatorsImplementer {
    public bool OperatorLess(int a, int b) {
         return a < b;
    }
}

class AnotherOperatorsImplementer {
    public bool OperatorLess(int a, int b) {
         return (a + 1) < (b - 1);
    }
}

class OperatorUser {
    int DoSomethingObscene(int a, int b, BooleanOperatorDelegate operator) {
        if (operator(a, b)) {
            return 5;
        }
        else {
            return -5;
        }
    }
}

Вы также должны проверить, что делегат, который вы получаете в качестве параметра, не равен NULL.

1
ответ дан 2 December 2019 в 04:25
поделиться

Вы имеете в виду, что объект будет иметь два ключа, или, скорее, ключ, состоящий из двух вещей.

Если вам нужен первый случай. То есть, для объекта с двумя ключами, например класса или объекта, вам нужно использовать две карты.

Map<Key1, value>

Map<Key2, value>

Во втором случае вам нужна карта карт, поэтому:

Map<Key1, Map<Key2, value>>
2
ответ дан 2 December 2019 в 04:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: