2

Is there a way to points several keys to the same value?
i.e.

HashMap<String, Float> mymap = new HashMap<>();
mymap.put("hello",5f);
mymap.put("bye",5f);
~somehow point bye and hello to the same value~
mymap.put("bye", mymap.get("bye") +5f)

mymap.get("hello") == 10
DsCpp
  • 2,259
  • 3
  • 18
  • 46

3 Answers3

4

Java HashMap stores references to Objects. If you store same object with two different keys, the keys will point to the same value.

But that is not your problem. Your problem is that you are using Float values and Float is an immutable data type. You can not change it's value once it has been created. To achieve what you want to do you need to either create a mutable Float or store the float in a container and store that container in the map. One of the most simple containers would be a single element array (though I would only use it in an example code, never in a production code as it is error prone and it is "self undocumentable").

HashMap<String, Float[]> mymap = new HashMap<>();
Float[] val = new Float[] { 5f };
mymap.put("hello", val);
mymap.put("bye", val);
...
mymap.get("bye")[0] = mymap.get("bye")[0] + 5f;

mymap.get("hello")[0] == 10f
Torben
  • 3,805
  • 26
  • 31
  • 3
    Correct analysis (problem is immutability). But using a _collection type_ (incl. array) for mutability is not a very good approach. Better write a mutable class for that purpose (I didn't find any in the JDK). – Seelenvirtuose Sep 06 '18 at 07:50
  • @Seelenvirtuose True. As I mentioned, I would use it only in an example code (for brevity). – Torben Sep 06 '18 at 07:51
  • 3
    Instead of `mymap.get("bye")[0] = mymap.get("bye")[0] + 5f;`, you can simply use `mymap.get("bye")[0] += 5;` By the way, I’d use `float[]` instead of `Float[]` here… – Holger Sep 06 '18 at 07:56
3

You would need a mutable object as Value for that, for example:

static class FLoatHolder {
    private float f;

    public FLoatHolder(float f) {
        this.f = f;
    }

    public float getF() {
        return f;
    }

    public void setF(float f) {
        this.f = f;
    }
}


    Map<String, FLoatHolder> map = new HashMap<>();
    FLoatHolder fh = new FLoatHolder(5f);
    map.put("bye", fh);
    map.put("hello", fh);

    FLoatHolder holder = map.get("bye");
    holder.setF(holder.getF() + 0.5f);

    map.put("bye", holder);

    System.out.println(map.get("hello").getF());
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • @DsCpp `float` is mutable, `Float` is not – Eugene Sep 06 '18 at 07:54
  • @DsCpp You are using floats but floats are primitive types and thtey can not be stored in a Map. The Java compiler tries to help you and automatically converts the floats to Floats. The action is called "autoboxing". – Torben Sep 06 '18 at 07:56
  • @DsCpp which accepted answer? You didn’t accept an answer. In case of [this answer](https://stackoverflow.com/a/52199027/2711488), it uses `Float[]`, an *array*, not a `Float` object. Whether you use a `FLoatHolder` instance or a single element array doesn’t make much difference. A dedicate class like `FLoatHolder` has the advantage that you can add specialized update operations needed by you application. – Holger Sep 06 '18 at 08:03
  • @Eugene neither, `Float` nor `float`, are mutable. You can change the value of variables of that type, but that also applies to both. E.g. you can write `float x = 10, y = x; x++;` and you can write `Float x = 10, y = x; x++;`. In either case, the `float` value `10f` or the `Float` object representing `10f` do not change, therefore, `y` is not affected by the change of `x`. – Holger Sep 06 '18 at 08:12
  • @Holger ha! :) indeed – Eugene Sep 06 '18 at 08:16
1

If you just want two keys to point to the same value, that is perfectly fine. Maps don't care what they point to, just that there aren't conflicting keys.

If you want to add the integer values together, then your pseudocode works as you intend.

If you want pointer like behavior where changing the value of key A affects the value of key B, then you'd have to make a wrapper object and use fields.

Something like:

class Pointer<T> {
    private T t;
    public Pointer(T t) {
        set(t);
    }
    public void set(T t) {
        this.t = t;
    }
    public T get() {
        return t;
    }
}
...
Map<String, Pointer> map = new HashMap<>();
Pointer<Integer> ptr = new Pointer<>(5);

map.put("A", ptr);
map.put("B", ptr);

System.out.println(map.get("A").get());
System.out.println(map.get("B").get());

ptr.set(25);

System.out.println(map.get("A").get());
System.out.println(map.get("B").get());

If you want something else you may need to elaborate or consider another data structure.

MeetTitan
  • 3,383
  • 1
  • 13
  • 26