0

I have a Hashmap HashMap <Integer, Integer> map and I want to change the keyset() type to a BinaryTreeNode, which was declared beforehand already, instead of an int, which I am able to do. However, I was wondering how could I add the appropriate map.values() in the same order as it was in my original HashMap map

Here is my code

public static BinaryTreeNode parentMapToTree(Map<Integer, Integer> map) {
    HashMap<BinaryTreeNode, Integer> l = new HashMap<>();
    for (int i = 0; i < map.keySet().size(); i++){
      BinaryTreeNode node = new BinaryTreeNode(i);
      l.put(node, map.values());
    }

What changes to my code should I make to ensure that this would compile and do as I want it o?

Droid
  • 520
  • 1
  • 7
  • I think you almost have it, but you're trying to put the entire old map into each key of the new map - instead you should only add what you get by looking up that particular key. – Edward Peters Nov 21 '22 at 15:41
  • 3
    Since a HashMap has no defined order asking if you can add anything to it "in the same order" doesn't make much sense. – OH GOD SPIDERS Nov 21 '22 at 15:41
  • Also it would be cleaner to iterate over the keys and values instead of using a for loop. In general for looping over indices like that is a discouraged practice in modern programming. – Edward Peters Nov 21 '22 at 15:42
  • @EdwardPeters so I could just say l.put(BinaryTreeNode, map.keyset())? – Droid Nov 21 '22 at 15:45
  • @OHGODSPIDERS what I meant was like add the values for every key correctly despite the change in data type. I'm not sure if changing the data type would change the value or not – Droid Nov 21 '22 at 15:46
  • ` l.put(BinaryTreeNode, map.keyset())` doesn't make any sense - give me a sec, I'll write up a more thorough answer. – Edward Peters Nov 21 '22 at 15:48
  • 4
    @Droid Then why not just Iterate over the entrySet? A simple `for(Entry entry : map.entrySet())` loop and then you can get the key and value via `entry.getKey();` and `entry.getValue();` (And do something like `l.put(new BinaryTreeNode(entry.getKey()), entry.getValue());` to fill your new map) – OH GOD SPIDERS Nov 21 '22 at 15:53

2 Answers2

1

If you need to maintain insertion order, you would need to create LinkedHashMap. HashMap doesn't gaurantee order.

  LinkedHashMap<BinaryTreeNode, Integer> l = new LinkedHashMap<>();

It works like a HashMap but preserves order.

aatwork
  • 2,130
  • 4
  • 17
1

First, some notes on what you have:

public static BinaryTreeNode parentMapToTree(Map<Integer, Integer> map) {
    HashMap<BinaryTreeNode, Integer> l = new HashMap<>();
    for (int i = 0; i < map.keySet().size(); i++){
      BinaryTreeNode node = new BinaryTreeNode(i);
      l.put(node, map.values());
    }

BinaryTreeNode node = new BinaryTreeNode(i); Is probably wrong - i is just the index, which doesn't really mean anything as HashMaps aren't ordered in any defined way.

l.put(node, map.values()); Is also wrong - here the value you're inserting is the entire original map.

You could save your current code by converting the keyset to an indexible structure (like a list - it's currently a set), and then grabbing the key at that index, converting it to a BinaryTreeNode, looking up the value associated with they key in the old map, and then adding both.

I probably have some syntax errors (I'm not in front of a compiler), but that would look something like:

public static BinaryTreeNode parentMapToTree(Map<Integer, Integer> map) {
    List keyList = ArrayList(map.keySet());
    HashMap<BinaryTreeNode, Integer> l = new HashMap<>();
    for (int i = 0; i < keyList().size(); i++){
      Integer key = keyList.get(i);
      BinaryTreeNode node = new BinaryTreeNode(key);
      l.put(node, map.get(key));
    }

But personally I think that's a really bad way to go about it.

What you probably want to do is instead iterate over the entry set:

public static BinaryTreeNode parentMapToTree(Map<Integer, Integer> map) {
    HashMap<BinaryTreeNode, Integer> l = new HashMap<>();
    for(Map.Entry<Integer, Integer> entry: map.entrySet()){
      BinaryTreeNode node = new BinaryTreeNode(entry.getKey());
      l.put(node, entry.getValue());
    }

This latter method is cleaner because it isn't manually mucking about with indices, which is generally a poor practice. Simpler still is to use a higher-order function, as in:

public static BinaryTreeNode parentMapToTree(Map<Integer, Integer> map) {
    HashMap<BinaryTreeNode, Integer> l = new HashMap<>();
    map.forEach((key,value) -> l.put(new BinaryTreeNode(key), value));
    }

That last one is skipping manual iteration altogether, and just passing the structure a function to run on each of its entries.

You can actually do one better, and skip initializing the new hashmap at all by using a map function (distinct from a HashMap data structure - totally different meaning.) See Java8: HashMap<X, Y> to HashMap<X, Z> using Stream / Map-Reduce / Collector for more on that.

Edward Peters
  • 3,623
  • 2
  • 16
  • 39