I'm trying to make a non-binary learning tree that's a simplified version of the ID3 algorithm. To do this, I tried to use enums, because there are several references teaching enum hierarchies, but I'm having trouble with the transfer of enums to the functions I need to make the tree. I've set up everything I need for the tree as best as I could, but I'm having trouble with the initial construction of the tree.
First, I made six enums, each with their own file so I wouldn't need to write "main.enumname" everywhere. These first five enums represent car diagnostics.
public enum fuelstats {notempty, empty}
public enum lightstatus {Dim, Normal}
public enum scents {normal, gas}
public enum soundstatus {Normal, Howl, Screech, Click}
public enum turn {no, yes}
Next, I made two more enums. One for the different diagnostic results, and one for the different "topics" of car diagnostics.
public enum problems {battery, starter, solenoid, outofgas, flooding}
public enum features {lightstatus, soundstatus, fuelstats, scents, turn, problems}
I then made five data examples of different car diagnostics to be sorted in the tree.
Example example1 = new Example(lightstatus.Dim, soundstatus.Howl, turn.yes, fuelstats.notempty, scents.normal, problems.battery);
Example example2 = new Example(lightstatus.Normal, soundstatus.Screech, turn.no, fuelstats.notempty, scents.normal, problems.starter);
Example example3 = new Example(lightstatus.Normal, soundstatus.Click, turn.no, fuelstats.notempty, scents.normal, problems.solenoid);
Example example4 = new Example(lightstatus.Normal, soundstatus.Normal, turn.yes, fuelstats.empty, scents.normal, problems.outofgas);
Example example5 = new Example(lightstatus.Normal, soundstatus.Normal, turn.yes, fuelstats.notempty, scents.gas, problems.flooding);
//make an array list of Examples.
ArrayList<Example> Examples = new ArrayList<Example>();
Examples.add(example1);
Examples.add(example2);
Examples.add(example3);
Examples.add(example4);
Examples.add(example5);
I put the various car diagnostics, called Features, in an ArrayList for shuffling purposes, because they will be randomly used to build the tree.
//This ArrayList holds the Enums for shuffling purposes.
ArrayList<features> Features = new ArrayList<features>();
Features.add(features.soundstatus);
Features.add(features.lightstatus);
Features.add(features.turn);
Features.add(features.scents);
Features.add(features.fuelstats);
// Shuffle the elements in the list
Collections.shuffle(Features);
//The Features Array List is now a shuffled tree.
//We will do a single loop that will serve as our stack.
//First we take the top of the list and assign it to the root.
Tree id3 = new Tree(Features.get(0),Examples);
But how do I write a tree that:
Takes in a feature enum that makes the subject of the root match the enum, and all of the different statuses of the enum the children? For example, if soundstatus is the root, it should make four children that are Normal, Howl, Screech, and Click. That way I can match the Example sounds with the children sounds. This is my node so far.
public class Node
{
ArrayList<Node> children;
/* Constructor*/
public Node(ArrayList<Node> ExampleList)
{
this.ExampleList = ExampleList;
this.parent = parent;
this.children = children;
}
public ArrayList<Node> getChildren()
{
return children;
}
public void addChild(Node n)
{
children.add(n);
}
private ArrayList<Node> children;
Enum phrase;
private boolean isUsed;
Node parent;
public void setUsed(boolean isUsed)
{
this.isUsed = isUsed;
}
public boolean isUsed()
{
return isUsed;
}
//This method states if the node is a leaf
public boolean isLeaf()
{
if (this.getChildren() == null)
return true;
else
return false;
}
}
you can add a child class to features:
import java.util.*;
interface hasEnumChildren {
Class clazz();
}
enum fuelstats {
notempty,empty
}
enum lightstatus {
Dim,Normal
}
enum scents {
normal,gas
}
enum soundstatus {
Normal,Howl,Screech,Click
}
enum turn {
no,yes
}
enum problems {
battery,starter,solenoid,outofgas,flooding
}
enum features implements hasEnumChildren {
lightstatus(lightstatus.class),soundstatus(soundstatus.class),fuelstats(fuelstats.class),scents(scents.class),turn(turn.class),problems(problems.class);
features(Class clazz) {
this.clazz=clazz;
}
final Class clazz;
#Override public Class clazz() {
return clazz;
}
}
public class So10233099 {
public static void main(String[] args) {
System.out.println(Arrays.asList(features.lightstatus.clazz().getEnumConstants()));
}
}
I had a similar problem, building an hierarchy of enums. But in my case, an hierarchy of classes could also do the trick. In case you are interested here is a question I posted:
How to build an hierarchy tree of categories in java using enums or any other way?
Now, concerning only enum hierarchy, as you can see above, I found that this may work for you:
http://alexradzin.blogspot.hk/2010/10/hierarchical-structures-with-java-enums_05.html
In particular:
public enum OsType {
OS(null),
Windows(OS),
WindowsNT(Windows),
WindowsNTWorkstation(WindowsNT),
WindowsNTServer(WindowsNT),
Windows2000(Windows),
Windows2000Server(Windows2000),
Windows2000Workstation(Windows2000),
WindowsXp(Windows),
WindowsVista(Windows),
Windows7(Windows),
Windows95(Windows),
Windows98(Windows),
Unix(OS) {
#Override
public boolean supportsXWindows() {
return true;
}
},
Linux(Unix),
AIX(Unix),
HpUx(Unix),
SunOs(Unix),
;
private OsType parent = null;
private OsType(OsType parent) {
this.parent = parent;
}
I hope it helps!
Related
I have a tree structure and I need to override the methods equals/hashCode because I use the check of the expected result in the unit tests.
The problem with tree type structures is that they refer to each other recursively. In particular, parents for children and vice versa.
and if all fields are used in the methods equals/hashCode, then there will be a looping. The question is how to correctly override then in order not to violate the contract.
I will give an example of how I implemented it.
public class App {
public static void main(String[] args) {
Book book1 = new Book(1L, "The catcher in the rye");
Book book2 = new Book(2L, "Rich Dad Poor Dad");
BookTree bookTree1 = new BookTree(book1);
BookTree bookTreeChild1 = new BookTree(book2);
bookTree1.addChild(bookTreeChild1);
BookTree bookTree2 = new BookTree(book1);
BookTree bookTreeChild2 = new BookTree(book2);
bookTree2.addChild(bookTreeChild2);
if (!bookTree1.equals(bookTree2)) {
throw new RuntimeException("Invalid override equals");
}
}
}
class Book {
private Long id;
private String name;
public Book(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
Book book = (Book) object;
return Objects.equals(id, book.id) &&
Objects.equals(name, book.name);
}
#Override
public int hashCode() {
return Objects.hash(id, name);
}
}
class Tree<T> {
private List<Tree<T>> children = new ArrayList<>();
private Tree<T> parent = null;
private T data;
public Tree(T data) {
this.data = data;
}
public Tree(T data, Tree<T> parent) {
this.data = data;
parent.addChild(this);
}
public List<Tree<T>> getChildren() {
return children;
}
public void addChild(Tree<T> child) {
child.setParent(this);
this.children.add(child);
}
public void addChild(T data) {
Tree<T> newChild = new Tree<>(data);
this.addChild(newChild);
}
public void removeChildren() {
this.children = new ArrayList<>();
}
public void addChildren(List<Tree<T>> children) {
for(Tree<T> t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
private void setParent(Tree<T> parent) {
this.parent = parent;
}
public Tree<T> getParent() {
return parent;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public boolean isRoot() {
return (this.parent == null);
}
public boolean isLeaf() {
return this.children.size() == 0;
}
public void removeParent() {
this.parent = null;
}
#Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
Tree<?> tree = (Tree<?>) object;
return Objects.equals(children, tree.children) &&
Objects.equals(data, tree.data);
}
#Override
public int hashCode() {
return Objects.hash(children, data);
}
}
class BookTree extends Tree<Book> {
public BookTree(Book data) {
super(data);
}
public BookTree(Book data, Tree<Book> parent) {
super(data, parent);
}
}
As you can see from my implementation, I use only two fields: "data" and "children".
Accordingly, my question is whether I implemented the methods equals/hashCode correctly?
If wrong, then please show how.
Accordingly, my question is whether I implemented the methods equals/hashCode correctly?
First of all: "what is correct?" ... one could wonder why a Tree should implement equals() and hashCode() in the first place. Especially hashCode() is tricky: the point of that method is (mainly) so you can store the corresponding object in a HashMap/HashSet. But that raises a big red flag: both these classes do not like it, when hashCode() returns different values over time. And that is exactly what your code will be doing: every time you change your tree (adding/removing a node), hashCode() will give a different result.
So we could have a look at what the standard libs do: and there we find JTree ... which doesn't implement both methods! On the other hand, when we look towards AbstractSet (which is the base class for TreeSet), there we find that both methods are implemented and include the members. So both ways seem to be valid.
Coming back to the question: that really depends how you want these two methods to work. Are two trees equal when they have the exact same content (meaning: does the order of children matter)?
Long story short: assuming that you want to ensure that all data is equal, and that all children are equal, and in the same order, then your implementation seems correct.
And yes, that restriction to only check these two attributes makes a lot of sense: when you include the parent link, you immediately get into a recursion that can't be broken.
Finally: you tagged this question with JUnit. This implies that you consider writing tests for your production code. Then these tests should answer your question. Meaning: one approach would be that you sit down and define the contract for these two methods. And then you create a number of test cases that verify all aspects of these contracts. And then your test cases tell you whether your production code meets your contract.
I think that is the crucial point here: there is no universal rule that tells us if/how to implement equals() and hashCode() for a Tree class. You have to look into your requirements if/how to do that. Then you derive tests from that knowledge, which you then you apply in order to verify if a given implementation meets the requirements/contract.
I think #GhostCat's answer where they ask "what is correct?" is crucial. I would like to focus on this part.
The sample given in the OP can be considered correct.
I would name the Tree class TreeNode, however. I think that's a more appropriate name. Then the question becomes are two TreeNodes equal if they have the same data and same children but a different parent? That's the current implementation of the OP. This can be considered correct. If, however, the requirement is that a TreeNode also has the same parent, then the entire tree must be equal when comparing two tree nodes. In that case, it doesn't really make sense to ever compare two tree nodes, why not just compare the two trees from the root node? I say this, because there is value in comparing two nodes within the tree and ask the question, "Are these two subtrees equal, regardless of the different parent?" So I believe the OP's code offers more flexibility than requiring that the parent also be equal. In this case the parent property is used for convenient navigation and not for identity. You can also imagine a TreeNode where there is no parent property and only the parent knows of its children. This would make data integrity easier to maintain (because the link is only stored in the parent), but navigation more challenging).
I favor the approach of thinking of parent as used for navigation or simply removing the parent property from TreeNode (or Tree as the OP calls the class).
I have entity AdminResource. Table has columns:
id | resource | path | parent | slug
1 Sport 1 0 sport
2 Football 1-2 1 sport-football
3 Estonia 1-2-3 2 sport-football-estonia
In my controller I get data
List<AdminResource> resources = resourceDAO.findAdminResources(user_id);
But I have problem now. I want to make new formated array/object with children items. Like this (by PHP, Javascript experience):
0: {
id: 1,
resource: Sport,
children: {
0: {
id: 2,
resource: Football,
children: {
id:....
}
}
}
}
Children can be very deep.
How I can create multidimensional array?
I this know in PHP and in Nodejs.
But in Java I have had a lot of errors.
Yes, I know about recursive logic. But...
I can't create with ArrayList, because I got error - key must be int.
I don't understand about HasMap, how I can create deep list.
I can't find similar examples in Google, maybe I can't understand its.
I can't understand how need work with multidimensional arrays/object in Java.
As finrod already explained, arrays are not what you are looking for. Judging by the {} syntax in your example, it looks more like a hierarchy of objects.
A tree seems to be a good option. As I said in my comment, a tree consists of nodes that hold a value (AdminResource in this case) and have children (a list of other nodes).
Here is a very basic example:
public static void main(String[] args)
{
List<AdminResource> resources = Arrays.asList(new AdminResource("Sport", Arrays.asList(1)),
new AdminResource("Football", Arrays.asList(1, 2)),
new AdminResource("Estonia", Arrays.asList(1, 2, 3)));
AdminNode root = new AdminNode(new AdminResource("ROOT", Collections.emptyList()));
resources.forEach(root::addResource);
for (AdminResource r : root)
{
System.out.println(r.getId());
}
}
public static class AdminNode
implements Iterable<AdminResource>
{
private AdminResource resource;
private List<AdminNode> children;
public AdminNode(AdminResource resource)
{
this.resource = resource;
this.children = new ArrayList<>();
}
public void addResource(AdminResource resource)
{
addResource(resource, new LinkedList<>(resource.getPath()));
}
private void addResource(AdminResource resource, Queue<Integer> path)
{
if (path.size() > 1)
{
Integer nextParent = path.poll();
for (AdminNode child : children)
{
if (child.getResource().getId().equals(nextParent))
{
child.addResource(resource, path);
}
}
}
else
{
children.add(new AdminNode(resource));
}
}
public AdminResource getResource() { return resource; }
#Override
public Iterator<AdminResource> iterator()
{
return stream().iterator();
}
public Stream<AdminResource> stream()
{
return goDown(this).skip(1).map(AdminNode::getResource);
}
private static Stream<AdminNode> goDown(AdminNode node)
{
return Stream.concat(Stream.of(node), node.children.stream().flatMap(AdminNode::goDown));
}
}
public static class AdminResource
{
private Integer id;
private String resource;
private List<Integer> path;
public AdminResource(String resource, List<Integer> path)
{
this.id = path.isEmpty() ? null : path.get(path.size() - 1);
this.resource = resource;
this.path = path;
}
public Integer getId() { return id; }
public List<Integer> getPath() { return path; }
}
The important class is AdminNode. You start with a dummy root node, which offers a method to add more AdminResources. That method recursively crawls down the path of the new resource, and finds the right place to add it. Similar methods can be written for removal or searching.
As I said, this a very basic example. It assumes that your list of resources is properly order. It ignores resources if the path to them is not existent yet. And so on...
But this should give you an idea of what trees are and how to start. They are used in a lot of places. A common usage is the component hierarchy of a User Interface, for example.
From what I can gather from the data you provided, I think what you want isn't a multidimensional array.
I think a tree or maybe an oriented graph if there can be multiple parents (same as the tree except a Node would have an array of parent nodes) is what you want.
I have some experience in Java and I am learning Ruby. I encountered a ruby program as below:
class Tree
attr_accessor :children, :node_name
def initialize(name, children=[])
#children = children
#node_name = name
end
def visit_all(&block)
visit &block
children.each {|c| c.visit_all &block}
end
def visit(&block)
block.call self
end
end
ruby_tree = Tree.new( "Ruby" ,
[Tree.new("Reia" ),
Tree.new("MacRuby" )] )
puts "Visiting a node"
ruby_tree.visit {|node| puts node.node_name}
puts
puts "visiting entire tree"
ruby_tree.visit_all {|node| puts node.node_name}
When I looked at the power of ruby language, I thought to write similar code in Java as below:
public class Tree {
private String name;
private Tree[] children;
Tree(String name, Tree[] children) {
this.name = name;
this.children = children;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Tree[] getChildren() {
return children;
}
public void setChildren(Tree[] children) {
this.children = children;
}
public static void main(String[] args) {
Tree myTree = new Tree("Ruby", new Tree[] {
new Tree("Reia", new Tree[] {}),
new Tree("MacRuby", new Tree[] {}) });
myTree.visit();
myTree.visit_all();
}
public void visit() {
System.out.println(getName());
}
public void visit_all() {
visit();
for (Tree tree : children) {
tree.visit();
}
}
}
Question:
I know that the java version here is not much flexible as Ruby.Is there anything similar in Java that I can do to achieve the level of flexibility like ruby does provides?
First, a word of caution: that code is absolutely horrible. It provides almost no encapsulation, it leaks implementation details left and right, there's no way that a Tree object can maintain its own invariants or state. Secondly, it doesn't integrate at all with Ruby's collection framework.
As a consequence, my Java translation is also equally horrible, and it also doesn't integrate with Java's collection framework.
The two biggest drawbacks that your Java code has compared to your Ruby are
in the Java version, the element type is hard-coded to String, whereas in the Ruby version, it can be any object, and even a mixture of objects within the same tree, and
in the Java version, the iterators are hard-coded to printing the name(s), whereas in the Ruby version, the iterators take a block argument with the code to execute.
The first problem cannot be easily solved in Java. You can make the collection generic, so that it can hold elements of any type, but making it heterogeneous (i.e. being able to hold elements of different types in the same collection) is going to be a lot of work. So, I stuck with the partial solution: making the Tree generic.
The second problem can be solved by having the iterators take an object which contains the code. After all, a first-class subroutine is basically the same as an object with only one method. (Java 8 is going to take some of that pain away, I included examples in the code.)
import java.util.Collection;
import java.util.ArrayList;
interface Consumer<T> {
void accept(T e);
}
// In Java 8, this interface is already part of the JRE.
// Just replace the 3 lines above with this import:
//import java.util.function.Consumer;
class Tree<T> {
private String nodeName;
private Collection<Tree<T>> children = new ArrayList<>();
Tree(String name, Collection<Tree<T>> children) {
nodeName = name;
this.children = children;
}
Tree(String name) {
nodeName = name;
}
public String getNodeName() { return nodeName; }
public void setNodeName(String name) { nodeName = name; }
public Collection<Tree<T>> getChildren() { return children; }
public void setChildren(Collection<Tree<T>> children) { this.children = children; }
void visitAll(Consumer<Tree<T>> block) {
visit(block);
for (Tree<T> tree : children) tree.visitAll(block);
}
void visit(Consumer<Tree<T>> block) {
block.accept(this);
}
public static void main(String... args) {
ArrayList<Tree<String>> children = new ArrayList<>();
children.add(new Tree<String>("Reia"));
children.add(new Tree<String>("MacRuby"));
Tree<String> rubyTree = new Tree<>("Ruby", children);
System.out.println("Visiting a node");
rubyTree.visit(new Consumer<Tree<String>>() {
public void accept(Tree<String> node) {
System.out.println(node.getNodeName());
}
});
// In Java 8, you can use a lambda.
// Just replace the 5 lines above with this line:
//rubyTree.visit(node -> System.out.println(node.getNodeName()));
System.out.println();
System.out.println("Visiting entire tree");
rubyTree.visitAll(new Consumer<Tree<String>>() {
public void accept(Tree<String> node) {
System.out.println(node.getNodeName());
}
});
// In Java 8, you can use a lambda.
// Just replace the 5 lines above with this line:
//rubyTree.visitAll(node -> System.out.println(node.getNodeName()));
}
}
def visit(&block)
block.call self
end
is more nicely written as
def visit
yield self
end
Also, visit_all and visit would be more idiomatically written as conforming to the Enumerable module:
class Tree
include Enumerable
# ...
def each(&cb)
cb.call(#element)
children.each end |child|
child.each(&cb) if child.respond_to?(:each)
end
end
end
This way, you get various other things for free, like e.g. max... and also, everyone knows each applies a block to all elements, while they would have to dig through your API docs or your code to see that the function is called visit_all.
EDIT: a chunk removed because I'm apparently an idiot. Thanks to steenslag for setting me right.
Let's say I have a Node class that has a Function as an instance variable.
public class Node {
private Function<Node, Double> function;
...
I have a List of these Nodes:
List<Node> nodes = Lists.newLinkedList();
nodes.add(new Node(someFunction));
nodes.add(new Node(someOtherFunction));
I can do this:
public Collection<Double> getValues() {
SomeFunction f = new SomeFunction();
return Collections2.transform(nodes, f);
}
Sure enough, transform iterates over the nodes List and applies the function f to each element like mapcar.
What I'm trying to do is to have transform use the function that each node element has.
So I though that the Supplier would help.
class NodeSupplier implements Supplier<Node> {
Iterator<Node> iterator;
NodeSupplier(Iterable p) {
iterator = Iterators.cycle(p);
}
#Override
public Node get() {
return iterator.next();
}
}
Then a Function to get a Node.
class SupplierGetter implements Function<Supplier<Node>, Node> {
#Override
public Node apply(Supplier<Node> from) {
return from.get();
}
}
Then compose them:
FunctionGetter fg = new FunctionGetter();
NodeSupplier sup = new NodeSupplier(this); // the this class is Iterable
Supplier<Function<Node, Double>> supplier = Suppliers.compose(fg, sup);
But then it gives me a type mismatch when I try to use it:
Collections2.transform(nodes, supplier);
it wants suppler.get() which is called once.
Collections2.transform(nodes, supplier.get());
Is there an easier way?
I saw mention of
Suppliers.supplierFunction()
but that seem s to not exist in verison r09.
I'm confused by what you're trying to do... Supplier doesn't seem useful here. Each Node has its own Function. You want to transform a collection of Nodes by applying each Node's Function to itself. So why not just give the Node class some method:
// may want a better name
public Double applyFunction() {
return function.apply(this);
}
Then you'd just transform using a Function like this:
public Double apply(Node node) {
return node.applyFunction();
}
Apart from the fact that I also have my doubts about what you are trying to do, the following should achieve what you are asking for:
class Node {
private Function<Node, Double> function;
private static Function<Node,Double> applyFunction = new Function<Node,Double>() {
#Override
public Double apply(final Node input) {
return input.function.apply(input);
}
};
public static Iterable<Double> transform(final Iterable<Node> nodes) {
return Iterables.transform(nodes, applyFunction);
}
}
There is a third way to do this without modifying the Node class, if we suppose that Node exposes its function through a public getter.
Using an anonymous class :
public Collection<Double> getValues() {
return Collections2.transform(nodes, new Function<Node, Double>() {
#Override public Double apply(Node node) {
return node.getFunction().apply(node);
}
});
}
Using the enum singleton pattern (which I prefer, since it's clearer) :
public Collection<Double> getValues() {
return Collections2.transform(nodes, ApplyNodeFunction.INSTANCE);
}
/**
* A {#link Function} that applies the {#link Node}'s own function on itself.
*/
private enum ApplyNodeFunction implements Function<Node, Double> {
INSTANCE;
#Override public Double apply(Node node) {
return node.getFunction().apply(node);
}
}
The key to my question was this phrase: "So I thought that the Supplier would help." The answer is that it doesn't. I was trying to find a use for it - outside of Map creation which seems to be its main use. There was that one Suppliers method I mentioned but it seems to be MIA. Perhaps this could be an RFI for tranform be overloaded to take an Iterable as the second parameter
I am trying to implement a recursive tree structure with arbitrary keys in Java. Basically what I want is to have a Tree<X,Y> which holds an X and more (sub)Trees, indexed by a set of Ys. However, I think that since the trees will be used for indexing data in a readonly disk file, the Tree itself should be read-only. So, in order to create them, I made a subclass, MutableTree, which should allow editing operations on a Tree.
Here is my code:
public class Tree<C,K> implements Serializable {
protected C content;
protected java.util.HashMap<K, Tree<C,K>> nexts;
protected Tree () {}
public C getContent() {
return content;
}
public java.util.Iterator<K> getKeys () {
return nexts.keySet().iterator();
}
public Tree<C,K> descend(K key) {
return nexts.get(key);
}
}
And for the MutableTree:
public class MutableTree<C,K> extends Tree<C,K> {
public MutableTree (Tree<C,K> par) {
super();
this.content = par.content;
this.nexts = par.nexts;
}
public MutableTree () {
super();
}
public void setContent (C c) {
this.content = c;
}
public MutableTree<C,K> addKey (K k) {
MutableTree<C,K> noo = new MutableTree<C,K>();
nexts.put(k, noo);
return noo;
}
public boolean delKey (K k) {
return (nexts.remove(k)!=null)?true:false;
}
}
This snippet does not compile, opting instead to complain that Tree.content and Tree.nexts are protected. As you can see, they indeed are. However, as MutableTree is a subclass of Tree, shouldn't it have access to its parent's protected fields?
Thanks for any help.
You can only access protected members through references of the same type as your code, or subtype.
Just as well in your case, because creating a MutableTree would allow client code to mutate a supposedly immutable Tree.