1

Question:

I'm implementing a recursive add() method on a tree type datastructure, implemented with a generic class representing tree nodes.

How can I create a sub-tree in that recursion, if the sub-tree is a generic type - thus has no constructor I can call?

Details of Situation:

I have a generic class set (which underneath is a map) that is designed to implement maps of maps of maps of ... of objects (basically, N level tree).

public interface NodeInterface<KeyType, ValueType> {
    public void add(List<KeyType>, ValueType);
    public ValueType getSubTree(KeyType); // Get subtree map
}

// Generic map class. 
// Leaf level nodes are maps too, just not maps containing other maps
public abstract class NodeMap <KeyType, ValueType> implements NodeInterface<> {
    protected Map<KeyType, ValueType> map; // actual map
    ...

}

// Leaf level objects - map NOT containing other maps
public class LeafNode extends NodeMap <String, MyDataType> {
    public void add(List<KeyType>, ValueType) {} // implementation for leaf add
    ...
}

// Tree nodes (non-leaf)
public class ParentNodeMap <ValueType extends NodeMap <?,?>>
    extends NodeMap <String, ValueType> {
     // This class is needed because there are methods that must be 
     // implemented on a map that can't be implemented on leaf level nodes.
     ...
}

// Actual tree node classes (needed as syntactic sugar, to avoid end users 
// having to deal with HashMap<String, Hashmap<String, HashMap<String, ...MyDataType>>>>>
public class Level2Node extends ParentNodeMap <LeafNode> {
}
public class Level1Node extends ParentNodeMap <Level2Node > {
}

What needs to be done:

I'm trying to implement a method which will recursively insert the leaf level object into this map of map of maps (described in the interface).

E.g., the desired behavior is:

tree = new Level1Node();
List<String> keys = Arrays.asList("key1", "key2"); // I think I need 3 here? irrelevant.
MyDataType data = new MyDataType();
tree.add(keys, data);

Problem:

I can't seem to implement creation and insertion of the subtree map in the add() method for ParentNode

This is what I tried in ParentNodeMap class:

public void add(List<KeyType> keys, ValueType value);
    KeyType key = getFirstKey(keys);
    createMapIfNull(); // creates "map" as new HashMap<KeyType, ValueType>()
    ValueType subTree = getSubTree(key); // Gets me child subtree from map
    // PROBLEM! that subtree is now "null" since we just created an new Map 
    // which has no key "hey"

    // Now here's where we should create a new subtree and add it:
    if (subTree == null) {
        subTree = new ValueType<>(); // THIS IS WHAT FAILS!!!!
        map.put(key, subTree);
        subTree.add(keys.removeFirstKey(), value); // recursively add to subtree
    }

Now, what I'm specifically stuck on is: How can I create an subTree object (of NodeMap type); where its type is generic ValueType extends NodeMap <?,?> and that's all I know of it?

Calling new ValueType() gives "Cannot instantiate the type ValueType" error.

DVK
  • 126,886
  • 32
  • 213
  • 327
  • You need a `Supplier`. – Andy Turner Jul 03 '17 at 15:01
  • As a side note: this is Java 8; so I'm comfortable with any solution that requires Java 8 capabilities (including functional programming) – DVK Jul 03 '17 at 15:02
  • 1
    Note: there are *many* questions asking the same. – Andy Turner Jul 03 '17 at 15:05
  • @AndyTurner I think the answer to this one would be quite different, because this class structure appears to have a logical error (i.e. this is an X\Y problem). Voting to re-open. – Sergey Kalinichenko Jul 03 '17 at 15:07
  • @dasblinkenlight - if there's one, it may be in the simplification I did to create a minimal example (or it may be in the original idea, of course :) – DVK Jul 03 '17 at 15:19
  • @dasblinkenlight - correct. ValueType is just a generic type of map value; if the map is a leaf level map it's the type of data (MyDataType); if the map is NOT a leaf level map then ValueType is the type of child node for that parent. I can see how that may be rather confusing, **perhaps I did over-generalized a mite**. – DVK Jul 03 '17 at 15:27
  • "the sub-tree is a generic type - thus has no constructor I can call" is a false premise. Mutable types are often bad choices for keys, especially collections. With all the code you omitted and the tangled logic of the fragments you did share it's hard to be sure, but it looks like you know that the node is of type `Node`, so I don't understand the difficulty. (Not good type names, btw.) – Lew Bloch Jul 03 '17 at 15:32
  • @LewBloch- the real type names make semantic context in the app. I renamed the types to try to fit the simplified examples, sorry for confusion – DVK Jul 03 '17 at 15:36

0 Answers0