Java multidimensional array for navigation - java

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.

Related

How to correctly implement equals(), hashCode() for Tree in Java?

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).

Using instances of a class as reference

I need some help on my class design or better said a reference to a common design pattern for a problem.
I am working in the aircraft industry. So far my programming skills are VBA and basic JAVA applications.
As an engineer my task is to create CAD Models for fixating components in and on to aircraft kitchens. To ensure a high reusability and to reduce development time I want to create a program which can recommend previous solutions.
Basically each aircraft operator can select from a catalog which galleys/kitchens (Monument) it would like to have installed. Inside these Monuments are multiple compartments. Inside a compartment we can install multiple equipment’s/components.
I would like to write a program which can tell me "you have installed these components together before -> In this compartment -> in that aircraft for that customer"
I have modeled the compartment, the monuments, and the aircraft. Each class extends form the same class BaseHolder:
public abstract class BaseHolder <I> {
private final ArrayList <I> heldItems = new ArrayList<I>();
public boolean addItem(final I i){
Objects.requireNonNull(i, "cannot add NULL");
return heldItems.add(i);
}
public boolean removeItem(I i){
return heldItems.remove(i);
}
public boolean contains(I i){
return heldItems.contains(i);
}
public int itemCount(){
return heldItems.size();
}
public boolean isEmpty(){
return heldItems.isEmpty();
}
public void Clear() {
heldItems.clear();
}
protected List<I> getHeldItems(){
return heldItems;
}
public I getElement(int n){
return heldItems.get(n);
}
}
public class Aircraft extends BaseHolder<Monument> {
// code
}
public class Monument extends BaseHolder<Compartment> {
private String name;
public Monument (String name){
this.setName(name);
}
// code
#Override
public boolean addItem(final Compartment c) {
Objects.requireNonNull(c, "cannot add NULL");
if (contains (c) ){
throw new IllegalArgumentException("Compartment already added!");
};
for(Compartment ctmp : getHeldItems()){
if (ctmp.getName().equals(c.getName() ) ) {
throw new IllegalArgumentException("Compartment with an identical name already exits");
}
}
return getHeldItems().add(c);
}
public Compartment getCompartment(int n){
return getHeldItems().get(n);
}
public Compartment getCompartment(String name){
for(Compartment ctmp : getHeldItems()){
if (ctmp.getName().equals(name) ) {
return ctmp;
}
}
return null;
}
}
public class Compartment extends BaseHolder<IWeighable>{
private String name = "";
private double MAX_LOAD = 0.0;
public Compartment (String name ,final double max_load){
this.setName(name);
updateMaxLoad(max_load);
}
// code
protected double getTotalLoad(){
// code
}
/**
*
* #param load
* #throws InvalidParameterException if max load not >= than 0.0
*/
public void setMaxLoad(final double load){
if (load >= 0.0){
this.MAX_LOAD = load;
} else {
throw new InvalidParameterException("max load must be greater than 0.0");
}
}
public boolean isOverloaded(){
return (getTotalLoad() > MAX_LOAD ) ;
}
}
The problem I am having is that this design seems to have many flaws. Apart from it being rather tedious: getElement(n).getElement(n).getElement(n)
Adding elements to a compartment results in all aircrafts using the same compartment, having all the same equipment’s/components installed. As it is the same object in the DB. An instance of the compartment would be need. Cloning the DB Compartment before adding it to an aircraft is no option. I need to be able to change the allowable loads, a change it for all. To resolve this I thought of using some type of “wrapper” class as in:
public class MonumentManager {
public ArrayList <Monument> monuments = new ArrayList<>();
public ArrayList <LinkObect> links;
class LinkObect{
private Compartment c;
private IWeighable e;
LinkObect(Compartment c, IWeighable e){
this.c = c;
this.e = e;
}
}
public boolean addMonument(Monument m){
return monuments.add(m);
}
public void addElementToCompartment(IWeighable e, Compartment c){
boolean known = false; //to check if the passed compartment is known/handeld to/by the MonumentManager
for (Monument m : monuments){
if ( m.getCompartment(c.getName() ) != null ) known = true;
}
if (known){
links.add(new LinkObect(c, e));
} else {
throw new IllegalArgumentException("Compartment is not inside a managed Monument!");
}
}
public List<Compartment> whereUsed(IWeighable e){
// TODO
}
}
This class might solve the problem but it is feels odd. Can anybody point me in the right direction towards a common design pattern etc. I am reading a book from the local library on design patterns. But it seems to be slightly above me. (as is maybe my task).
Any suggestions / help etc would be highly appreciated.
I hope I'm understanding this correctly.
One thing is the Component you want to install that has certain characteristics and another thing is some representation of what you have installed.
The information of your installation does not need to be in your Component but in something else, let's call it Installation.
Your Installation has to know 2 things:
What kind of Component it is.
What other Installations it has inside.
The installation will look something like this.
public class Installation {
private Component type;
private List<Installation> content;
public Installation(Component type){
this.type = type;
this.content = new ArrayList<Component>();
}
//you can have methods for add, remove, etc...
}
Feel free to ask further clarifications.

How To Do Recursive Observable Call in RxJava?

I am quite new to RxJava (and Reactive paradigm in general), so please bear with me.
Suppose I have this News and this nested Comment data structure:
public class News {
public int id;
public int[] commentIds; //only top level comments
public News(int id, int[] commentIds) {
this.id = id;
this.commentIds = commentIds;
}
}
public class Comment {
public int id;
public int parentId; //ID of parent News or parent comment
public int[] childIds;
public Comment(int id, int parentId, int[] childIds) {
this.id = id;
this.parentId = parentId;
this.childIds = childIds;
}
}
and suppose I have this API endpoint:
getComments(int commentId) //return Observable<Comment> for Comment with ID commentId
Now, let's assume:
getComments(1); //will return Comment(1, 99, [3,4])
getComments(2); //will return Comment(2, 99, [5,6])
getComments(3); //will return Comment(3, 1, [])
getComments(4); //will return Comment(4, 1, [])
getComments(5); //will return Comment(5, 2, [])
getComments(6); //will return Comment(6, 2, [])
**
Now, if I have News n = News(99, [1,2]), how do I get all of its children comment recursively? i.e. to get comments with ID [1,2,3,4,5,6]?
**
I have searched and stumbled upon this: https://jkschneider.github.io/blog/2014/recursive-observables-with-rxjava.html
This is the recursion function:
public class FileRecursion {
static Observable<File> listFiles(File f) {
if(f.isDirectory())
return Observable.from(f.listFiles()).flatMap(FileRecursion::listFiles);
return Observable.just(f);
}
public static void main(String[] args) {
Observable.just(new File("/Users/joschneider/Desktop"))
.flatMap(FileRecursion::listFiles)
.subscribe(f -> System.out.println(f.getAbsolutePath()));
}
}
It shows an example on how to do recursive observable calls, but the inner function (f.listFiles()) is a blocking operation (doesn't return another Observable). In my case, the inner function (getComments) is a non-blocking function that returns another Observables. How do I do that?
Any help will be much appreciated.
This does practically the same thing described in the article:
Observable<Comment> getInnerComments(Comment comment) {
if (comment.childIds.length > 0)
return Observable.merge(
Observable.just(comment),
Observable.from(comment.childIds)
.flatMap(id -> getComments(id))
.flatMap(this::getInnerComments));
return Observable.just(comment);
}
public static void main(String[] args) {
getComments(1)
.flatMap(this::getInnerComments)
.subscribe(c -> System.out.println(comment.toString()));
}
I start with the comment with id = 1, then I pass it to getInnerComments(). The getInnerComments() checks if the comment has children. If it does, it iterates over every child id (Observable#from) and loads every child with your getComments(int) API. Then every child is passed to the getInnerComments() to do the same procedure. If a comment doesn't have children, it is immediately returned using Observable#just.
This is pseudo-code and it wasn't tested, but you should get the idea.
Below is an example of how to get all comments and then aggregate them to one List<Comment>.
getNews(99)
.flatMap(news -> Observable.from(news.commentIds))
.flatMap(commentId -> getComments(commentId))
.flatMap(comment -> getInnerComments(comment))
.toList()
.subscribe(commentList -> { });

How to write the best possible Java code for a similar Ruby functionality?

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.

ID3 Java Enum Tree

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!

Categories

Resources