So I can really get this I was wondering if anyone could help me out, the object of this program is to use the visitor pattern to generate a list of strings from the name of people in a given binary tree, if not really sure how to go about using an append function to do so. How would I append the person with its parents?
import tester.Tester;
//Representation for an ancestor tree
interface IAT {
<R> R accept(IATVisitor<R> visitor);
//Append two lists
IList<String> append(IList<String> l);
}
//-------------------------------------------------------------------------------------------------
//Unknown person
class Unknown implements IAT {
Unknown() {
}
public <R> R accept(IATVisitor<R> visitor) {
return visitor.visitUnknown(this);
}
//append two an unknown
public IList<String> append(IList<String> l) {
return l;
}
}
//-------------------------------------------------------------------------------------------------
//Representation for a person
class Person implements IAT {
String name;
int yob;
boolean isMale;
IAT mom;
IAT dad;
//Constructor
Person(String name, int yob, boolean isMale, IAT mom, IAT dad) {
this.name = name;
this.yob = yob;
this.isMale = isMale;
this.mom = mom;
this.dad = dad;
}
public <R> R accept(IATVisitor<R> visitor) {
return visitor.visitPerson(this);
}
//append parent and children of tree
public IList<String> append(IList<String> l) {
//
}
}
//-------------------------------------------------------------------------------------------------
interface IATVisitor<R> {
R visitUnknown(Unknown u);
R visitPerson(Person p);
}
//-------------------------------------------------------------------------------------------------
//IAT Visitor that returns a list of the names of all people
class IATVisitGetNames implements IATVisitor<IList<String>> {
public IList<String> visitUnknown(Unknown u) {
return new MT<String>();
}
public IList<String> visitPerson(Person p) {
return new Cons<String>(p.name, new MT<String>());
}
}
//Examples
class ExamplesIATV {
//persons
Unknown a = new Unknown();
Person ralph = new Person("Ralph", 1995, true, a, a);
Person kevin = new Person("Kevin", 1994, true, a , a);
Person julia = new Person("Julia", 1991, false, ralph, a);
Person lily = new Person("Lily", 1990, false, kevin, julia);
Person who = new Person("?", 1738, false, lily, a);
//Visitor
IATVisitor<IList<String>> byName = new IATVisitGetNames();
//test Vistior
boolean testGetNames(Tester t) {
return
t.checkExpect(who.accept(byName), new MT<String>());
}
}
First - you want collect all names from tree. You need traversal function, for example:
public void traverse(Node root) {
//do somesing with node
System.out.println(root.value);
if (root.left != null) {
traverse(root.left);
}
if (root.right != null) {
traverse(root.right);
}
}
Second - you want to use Visitor pattern. How wikipedia says:
Visitor - is a way of separating an algorithm from an object structure
on which it operates.
So visitor is not suitable for travers/itereate logic. With visitor we can only incapsulate some logic on node:
public void traverseWithVisitor(Node root, IVisitor v) {
root.accept(v);
if (root.left != null) {
traverseWithVisitor(root.left, v);
}
if (root.right != null) {
traverseWithVisitor(root.right, v);
}
}
Now incapsulate our collecting names logic in visitor:
class AggregateNamesVisitor implements IVisitor {
public List<Integer> names = new ArrayList<>();
#Override
public void visit(Node node) {
names.add(node.value);
}
}
We can use it like this:
AggregateNamesVisitor aggregateVisitor = new AggregateNamesVisitor();
traverseWithVisitor(root, aggregateVisitor);
aggregateVisitor.names.forEach(name -> System.out.print(" " + name));
Related
I want to convert a tree that represents a math expression into the actual math expression (a string like "a+b/c")
The tree representation is the simplest you could imagine:
A+B/C would be this tree:
OperationNode(+, A, OperationNode(/, B, C))
And (A+B)/C would be this tree:
OperationNode(/, OperationNode(+, A, B), C)
In order to convert the tree into the string, I'm using the Visitor pattern. The problem comes with parentheses.
My current Visitor implementation ALWAYS adds parentheses to the nodes, so every tree I generate turns into a string like this:
(((A+B)+C)+D)
Notice the redundant parentheses.
So the question is: how could I make my Visitor generate the string with no redundant parentheses?
As NelFeal wrote while walking the tree you just need to check if precedence of suboperation less than a precedence of the current operation.
I implemented visitor pattern for you, hope it helps.
enum Operation
{
Add,
Multiply,
Power,
UnaryMinus,
None,
}
static class OperationExtensions
{
public static string ToFriendlyString(this Operation me)
{
switch (me)
{
case Operation.None:
return "";
case Operation.Add:
return "+";
case Operation.Multiply:
return "*";
case Operation.Power:
return "^";
case Operation.UnaryMinus:
return "-";
default:
throw new ArgumentException();
}
}
}
class OperationNode
{
public Operation Op;
public OperationNode(Operation op)
{
Op = op;
}
}
interface IVisitor
{
void Visit(OperationNodeLeaf node);
void Visit(OperationNode1 node);
void Visit(OperationNode2 node);
}
sealed class Visitor : IVisitor
{
public string Text { get; set; }
private void Enclose(OperationNode subNode, Operation op)
{
if (subNode.Op < op)
{
Text = Text + "(";
Visit((dynamic)subNode);
Text = Text + ")";
}
else
{
Visit((dynamic)subNode);
}
}
public void Visit(OperationNodeLeaf node)
{
Text = Text + node.Op.ToFriendlyString();
Text = Text + node.Value.ToString();
}
public void Visit(OperationNode1 node)
{
Text = Text + node.Op.ToFriendlyString();
Enclose(node.SubNode, node.Op);
}
public void Visit(OperationNode2 node)
{
Enclose(node.LeftSubNode, node.Op);
Text = Text + node.Op.ToFriendlyString();
Enclose(node.RightSubNode, node.Op);
}
}
class OperationNodeLeaf : OperationNode
{
public int Value;
public OperationNodeLeaf(int v, Operation op = Operation.None) : base(op)
{
Value = v;
}
void Accept(IVisitor v)
{
v.Visit(this);
}
}
class OperationNode1 : OperationNode
{
public OperationNode SubNode;
public OperationNode1(OperationNode sn, Operation op) : base(op)
{
SubNode = sn;
}
void Accept(IVisitor v)
{
v.Visit(this);
}
}
class OperationNode2 : OperationNode
{
public OperationNode LeftSubNode;
public OperationNode RightSubNode;
public OperationNode2(OperationNode lsn, OperationNode rsn, Operation op) : base(op)
{
LeftSubNode = lsn;
RightSubNode = rsn;
}
void Accept(IVisitor v)
{
v.Visit(this);
}
}
class Program
{
static void Main(string[] args)
{
var tree =
new OperationNode2(
new OperationNode2(
new OperationNode2(new OperationNodeLeaf(5), new OperationNodeLeaf(6), Operation.Add),
new OperationNode2(new OperationNodeLeaf(5), new OperationNodeLeaf(6), Operation.Multiply),
Operation.Power
),
new OperationNode2(
new OperationNode2(new OperationNodeLeaf(1), new OperationNodeLeaf(2), Operation.Multiply),
new OperationNode1(new OperationNodeLeaf(7, Operation.None), Operation.UnaryMinus),
Operation.Add
),
Operation.Multiply
);
var visitor = new Visitor();
visitor.Visit(tree);
System.Diagnostics.Debug.WriteLine(visitor.Text);
}
}
(5+6)^(5*6)*(1*2+-7)
You need a operator precedence table. Simply assign precedence values to every operator you support (and maybe to the topmost no-op that gives you the outermost pair of parentheses). Then, for each operation node, if its operation has a higher precedence than the parent node operation, you don't need parentheses.
First of all: I'm not trying to re-invent the wheel, this is for purpose of study.
I'm quite a newbie in java world so be patient.
My aim is to build a public class to manage linked list with sorted insertion.
What I did so far (that is working) is:
import java.util.Iterator;
import package_Car.SortTypes;
class Node<E>
{
E data;
Node<E> next;
Node(E data, Node<E> node)
{
this.data = data;
this.next = node;
}
public Node<E> getNext()
{
return next;
}
}
public class SortedInsertionLinkedList<E> implements Iterable<Node<E>>
{
Node<E> root;
Sort_Types sort;
final class LinkedListIterator implements Iterator<Node<E>>
{
private Node<E> cursor;
LinkedListIterator(Node<E> root)
{
cursor = new Node<E>(null, null);
cursor = root;
}
public boolean hasNext()
{
return cursor != null;
}
public Node<E> next()
{
Node<E> retVal = cursor;
if (hasNext())
{
cursor = retVal.getNext();
}
return retVal;
}
}
public Iterator<Node<E>> iterator()
{
return new LinkedListIterator(root);
}
public SortedInsertionLinkedList(Sort_Types sort)
{
root = null;
this.sort = sort;
}
public void insert(E item)
{
if (item != null)
{
if (root == null)
{
root = new Node<E>(item, null);
}
else
{
Node<E> currNode = root;
Node<E> prevNode = null;
for (Node<E> currListNode : this)
{
if (sort.compareTo(currListNode.data, item) < 0)
{
prevNode = currListNode;
currNode = currListNode.next;
}
}
Node<E> t = new Node<E>(item, currNode);
if (prevNode == null)
root = t;
else
prevNode.next = t;
}
}
}
public void print()
{
for (Node<E> currNode : this)
{
System.out.print(currNode.data + " ");
System.out.println();
}
System.out.println();
}
public boolean find(E x)
{
for (Node<E> currNode : this)
{
int c = sort.compareTo(currNode.data, x);
if (c == 0)
return true;
if (c > 0)
return false;
}
return false;
}
public void delete(E x)
{
Node<E> prevNode = null;
for (Node<E> currNode : this)
{
int c = sort.compareTo(currNode.data, x);
if (c == 0)
{
if (currNode == root)
{
root = currNode.next;
}
else
{
prevNode.next = currNode.next;
}
return;
}
if (c > 0)
return;
prevNode = currNode;
}
}
}
As you can see I added to my class a private field that define which type of sort have to be used to compare linked list Nodes. This sort type is a enum
public enum Sort_Types
{
SORT_BY_NAME
{
public int compareTo(Object o1, Object o2)
{
Car item1 = (Car) o1;
Car item2 = (Car) o2;
return item1.nome.compareTo(item2.nome);
}
},
SORT_BY_PRICE
{
public int compareTo(Object o1, Object o2)
{
Car item1 = (Car) o1;
Car item2 = (Car) o2;
return Double.compare(item1.prezzo, item2.prezzo);
}
},
SORT_BY_GAIN
{
public int compareTo(Object o1, Object o2)
{
double gain1;
double gain2;
if (o1 instanceof CarSpecificInterface)
{
CarSpecificInterface dummy = (CarSpecificInterface) o1;
gain1 = dummy.gain();
}
else
{
throw new IllegalArgumentException();
}
if (o2 instanceof CarSpecificInterface)
{
CarSpecificInterface dummy = (CarSpecificInterface) o2;
gain2 = dummy.gain();
}
else
{
throw new IllegalArgumentException();
}
return Double.compare(gain2, gain1);
}
},
SORT_BY_URGENCY
{
public int compareTo(Object o1, Object o2)
{
double urgency1;
double urgency2;
if (o1 instanceof CarSpecificInterface)
{
CarSpecificInterface dummy = (CarSpecificInterface) o1;
urgency1 = dummy.urgency();
}
else
{
throw new IllegalArgumentException();
}
if (o2 instanceof CarSpecificInterface)
{
CarSpecificInterface dummy = (CarSpecificInterface) o2;
urgency2 = dummy.urgency();
}
else
{
throw new IllegalArgumentException();
}
return Double.compare(urgency2, urgency1);
}
};
public abstract int compareTo(Object o1, Object o2);
}
Why I did that? Because of class that can be used to instatiate the linked list are 3:
Car
New_Car that extends Car
Used_Car that extends Car
New_Car and Used_Car classes implements an interface
public interface Car_Specific_Interface
{
public double gain();
public double urgency();
}
So I can use my linked list for type Car that can accept (obviously) SubClasses
Sorted_Linked_List<Car> carsSortedByName;
Sorted_Linked_List<Car> carSortedByGain;
Sorted_Linked_List<Car> carSortedByUrgency;
public DB_Mng()
{
carsSortedByName = new Sorted_Linked_List<>(Sort_Types.SORT_BY_NAME);
carSortedByGain = new Sorted_Linked_List<>(Sort_Types.SORT_BY_GAIN);
carSortedByGain = new Sorted_Linked_List<>(Sort_Types.SORT_BY_URGENCY);
}
So, to sum up: I have a generic linked list with sorted insertion that can accept different classes and can be sorted by specific field or methods.
What I'd like to understand is if there is a way to do that changing classes hierarchy "simply" implementing Comparable interface.
Step one is to understand java generics.
Specifically,
java generics are a compile time feature;
they are in no way a java implementation of c++ templates.
You can not create a "fully general" sorted-on-insert list because Object does not implement any comparison functionality.
You can create a sorted-on-insert list of elements that implement some known interface or which extend a specific class.
I suggest to fully step back here. With Java8 and lambdas and streams one really does things differently in 2017. Or well, since years.
I recommend you looking into this presentation from the Java Forum Stuttgart 2014. A few starting words in German, but the rest is all code, and easy to grasp.
Thing is: you want to write code like:
collection .sort(
Comparator
.comparing(Person::getName)
.reversed()
.thenComparing(Person::getId)
);
and use lambdas / method references - instead of writing all that "manual boilerplate" code to access member fields for example.
If both NewCar and UsedCar are implementing Car_Specific_Interface you can just check interface in your comparators, like:
if (o1 instanceof Car_Specific_Interface)
{
Car_Specific_Interface dummy = (Car_Specific_Interface) o1;
gain1 = dummy.gain();
}
else
{
throw new IllegalArgumentException();
}
also you can make you compare function more complex to support Comparable and Comparator. For example:
private int compareItems(E firstItem, E secondItem) {
if (sort == null) {
if (firstItem instanceof Comparable && secondItem instanceof Comparable) {
return ((Comparable)firstItem).compareTo(secondItem);
} else {
throw new IllegalArgumentException("Failed to compare");
}
}
return sort.compareTo(firstItem, secondItem);
}
I am attempting to implement my first Factory Design Pattern, and I'm not sure how to avoid using instanceof when adding the factory-made objects to lists. This is what I'm trying to do:
for (Blueprint bp : blueprints) {
Vehicle v = VehicleFactory.buildVehicle(bp);
allVehicles.add(v);
// Can I accomplish this without using 'instanceof'?
if (v instanceof Car) {
cars.add((Car) v);
} else if (v instanceof Boat) {
boats.add((Boat) v);
} else if (v instanceof Plane) {
planes.add((Plane) v);
}
}
From what I've read on Stack Overflow, using 'instanceof' is a code smell. Is there a better way to check the type of vehicle that was created by the factory without using 'instanceof'?
I welcome any feedback/suggestions on my implementation as I'm not even sure if I'm going about this the right way.
Full example below:
import java.util.ArrayList;
class VehicleManager {
public static void main(String[] args) {
ArrayList<Blueprint> blueprints = new ArrayList<Blueprint>();
ArrayList<Vehicle> allVehicles = new ArrayList<Vehicle>();
ArrayList<Car> cars = new ArrayList<Car>();
ArrayList<Boat> boats = new ArrayList<Boat>();
ArrayList<Plane> planes = new ArrayList<Plane>();
/*
* In my application I have to access the blueprints through an API
* b/c they have already been created and stored in a data file.
* I'm creating them here just for example.
*/
Blueprint bp0 = new Blueprint(0);
Blueprint bp1 = new Blueprint(1);
Blueprint bp2 = new Blueprint(2);
blueprints.add(bp0);
blueprints.add(bp1);
blueprints.add(bp2);
for (Blueprint bp : blueprints) {
Vehicle v = VehicleFactory.buildVehicle(bp);
allVehicles.add(v);
// Can I accomplish this without using 'instanceof'?
if (v instanceof Car) {
cars.add((Car) v);
} else if (v instanceof Boat) {
boats.add((Boat) v);
} else if (v instanceof Plane) {
planes.add((Plane) v);
}
}
System.out.println("All Vehicles:");
for (Vehicle v : allVehicles) {
System.out.println("Vehicle: " + v + ", maxSpeed: " + v.maxSpeed);
}
System.out.println("Cars:");
for (Car c : cars) {
System.out.println("Car: " + c + ", numCylinders: " + c.numCylinders);
}
System.out.println("Boats:");
for (Boat b : boats) {
System.out.println("Boat: " + b + ", numRudders: " + b.numRudders);
}
System.out.println("Planes:");
for (Plane p : planes) {
System.out.println("Plane: " + p + ", numPropellers: " + p.numPropellers);
}
}
}
class Vehicle {
double maxSpeed;
Vehicle(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
class Car extends Vehicle {
int numCylinders;
Car(double maxSpeed, int numCylinders) {
super(maxSpeed);
this.numCylinders = numCylinders;
}
}
class Boat extends Vehicle {
int numRudders;
Boat(double maxSpeed, int numRudders) {
super(maxSpeed);
this.numRudders = numRudders;
}
}
class Plane extends Vehicle {
int numPropellers;
Plane(double maxSpeed, int numPropellers) {
super(maxSpeed);
this.numPropellers = numPropellers;
}
}
class VehicleFactory {
public static Vehicle buildVehicle(Blueprint blueprint) {
switch (blueprint.type) {
case 0:
return new Car(100.0, 4);
case 1:
return new Boat(65.0, 1);
case 2:
return new Plane(600.0, 2);
default:
return new Vehicle(0.0);
}
}
}
class Blueprint {
int type; // 0 = car; // 1 = boat; // 2 = plane;
Blueprint(int type) {
this.type = type;
}
}
You could implement the Visitor pattern.
Detailed Answer
The idea is to use polymorphism to perform the type-checking. Each subclass overrides the accept(Visitor) method, which should be declared in the superclass. When we have a situation like:
void add(Vehicle vehicle) {
//what type is vehicle??
}
We can pass an object into a method declared in Vehicle. If vehicle is of type Car, and class Car overrode the method we passed the object into, that object would now be processed within the method declared in the Car class. We use this to our advantage: creating a Visitor object and pass it to an overriden method:
abstract class Vehicle {
public abstract void accept(AddToListVisitor visitor);
}
class Car extends Vehicle {
public void accept(AddToListVisitor visitor) {
//gets handled in this class
}
}
This Visitor should be prepared to visit type Car. Any type that you want to avoid using instanceof to find the actual type of must be specified in the Visitor.
class AddToListVisitor {
public void visit(Car car) {
//now we know the type! do something...
}
public void visit(Plane plane) {
//now we know the type! do something...
}
}
Here's where the type checking happens!
When the Car receives the visitor, it should pass itself in using the this keyword. Since we are in class Car, the method visit(Car) will be invoked. Inside of our visitor, we can perform the action we want, now that we know the type of the object.
So, from the top:
You create a Visitor, which performs the actions you want. A visitor should consist of a visit method for each type of object you want to perform an action on. In this case, we are creating a visitor for vehicles:
interface VehicleVisitor {
void visit(Car car);
void visit(Plane plane);
void visit(Boat boat);
}
The action we want to perform is adding the vehicle to something. We would create an AddTransportVisitor; a visitor that manages adding transportations:
class AddTransportVisitor implements VehicleVisitor {
public void visit(Car car) {
//add to car list
}
public void visit(Plane plane) {
//add to plane list
}
public void visit(Boat boat) {
//add to boat list
}
}
Every vehicle should be able to accept vehicle visitors:
abstract class Vehicle {
public abstract void accept(VehicleVisitor visitor);
}
When a visitor is passed to a vehicle, the vehicle should invoke it's visit method, passing itself into the arguments:
class Car extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
class Boat extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
class Plane extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
That's where the type-checking happens. The correct visit method is called, which contains the correct code to execute based on the method's parameters.
The last problem is having the VehicleVisitor interact with the lists. This is where your VehicleManager comes in: it encapsulates the lists, allowing you to add vehicles through a VehicleManager#add(Vehicle) method.
When we create the visitor, we can pass the manager to it (possibly through it's constructor), so we can perform the action we want, now that we know the object's type. The VehicleManager should contain the visitor and intercept VehicleManager#add(Vehicle) calls:
class VehicleManager {
private List<Car> carList = new ArrayList<>();
private List<Boat> boatList = new ArrayList<>();
private List<Plane> planeList = new ArrayList<>();
private AddTransportVisitor addVisitor = new AddTransportVisitor(this);
public void add(Vehicle vehicle) {
vehicle.accept(addVisitor);
}
public List<Car> getCarList() {
return carList;
}
public List<Boat> getBoatList() {
return boatList;
}
public List<Plane> getPlaneList() {
return planeList;
}
}
We can now write implementations for the AddTransportVisitor#visit methods:
class AddTransportVisitor implements VehicleVisitor {
private VehicleManager manager;
public AddTransportVisitor(VehicleManager manager) {
this.manager = manager;
}
public void visit(Car car) {
manager.getCarList().add(car);
}
public void visit(Plane plane) {
manager.getPlaneList().add(plane);
}
public void visit(Boat boat) {
manager.getBoatList().add(boat);
}
}
I highly suggest removing the getter methods and declaring overloaded add methods for each type of vehicle. This will reduce overhead from "visiting" when it's not needed, for example, manager.add(new Car()):
class VehicleManager {
private List<Car> carList = new ArrayList<>();
private List<Boat> boatList = new ArrayList<>();
private List<Plane> planeList = new ArrayList<>();
private AddTransportVisitor addVisitor = new AddTransportVisitor(this);
public void add(Vehicle vehicle) {
vehicle.accept(addVisitor);
}
public void add(Car car) {
carList.add(car);
}
public void add(Boat boat) {
boatList.add(boat);
}
public void add(Plane plane) {
planeList.add(plane);
}
public void printAllVehicles() {
//loop through vehicles, print
}
}
class AddTransportVisitor implements VehicleVisitor {
private VehicleManager manager;
public AddTransportVisitor(VehicleManager manager) {
this.manager = manager;
}
public void visit(Car car) {
manager.add(car);
}
public void visit(Plane plane) {
manager.add(plane);
}
public void visit(Boat boat) {
manager.add(boat);
}
}
public class Main {
public static void main(String[] args) {
Vehicle[] vehicles = {
new Plane(),
new Car(),
new Car(),
new Car(),
new Boat(),
new Boat()
};
VehicleManager manager = new VehicleManager();
for(Vehicle vehicle : vehicles) {
manager.add(vehicle);
}
manager.printAllVehicles();
}
}
You can add method to vehicle class to print the text. Then override the method in each specialized Car class. Then just add all the cars to the vehicle list. And loop the list to print the text.
I'm not too happy with the lists of cars, boats and planes in the first place. You have multiple examples of reality but the list isn't inherently all-inclusive--what happens when your factory starts making submarines or rockets?
Instead, how about an enum with the types car, boat and plane. You have an array of lists of vehicles.
The generic vehicle has an abstract property CatalogAs, the various vehicles actually implement this and return the proper value.
Done some restructuring of your code. Hope that works for you. Check this:
import java.util.ArrayList;
class VehicleManager {
public static void main(String[] args) {
ArrayList<ABluePrint> bluePrints = new ArrayList<ABluePrint>();
ArrayList<AVehicle> allVehicles = new ArrayList<AVehicle>();
ArrayList<ACar> cars = null;
ArrayList<ABoat> boats = null;
ArrayList<APlane> planes = null;
/*
* In my application I have to access the blueprints through an API
* b/c they have already been created and stored in a data file.
* I'm creating them here just for example.
*/
ABluePrint bp0 = new ABluePrint(0);
ABluePrint bp1 = new ABluePrint(1);
ABluePrint bp2 = new ABluePrint(2);
bluePrints.add(bp0);
bluePrints.add(bp1);
bluePrints.add(bp2);
for (ABluePrint bp : bluePrints) {
AVehicle v = AVehicleFactory.buildVehicle(bp);
allVehicles.add(v);
// Can I accomplish this without using 'instanceof'?
// dont add objects to list here, do it from constructor or in factory
/*if (v instanceof ACar) {
cars.add((ACar) v);
} else if (v instanceof ABoat) {
boats.add((ABoat) v);
} else if (v instanceof APlane) {
planes.add((APlane) v);
}*/
}
cars = ACar.getCars();
boats = ABoat.getBoats();
planes = APlane.getPlanes();
System.out.println("All Vehicles:");
for (AVehicle v : allVehicles) {
System.out.println("Vehicle: " + v + ", maxSpeed: " + v.maxSpeed);
}
System.out.println("Cars:");
for (ACar c : cars) {
System.out.println("Car: " + c + ", numCylinders: " + c.numCylinders);
}
System.out.println("Boats:");
for (ABoat b : boats) {
System.out.println("Boat: " + b + ", numRudders: " + b.numRudders);
}
System.out.println("Planes:");
for (APlane p : planes) {
System.out.println("Plane: " + p + ", numPropellers: " + p.numPropellers);
}
}
}
class AVehicle {
double maxSpeed;
AVehicle(double maxSpeed) {
this.maxSpeed = maxSpeed;
}
void add(){}
}
class ACar extends AVehicle {
static ArrayList<ACar> cars = new ArrayList<ACar>();
int numCylinders;
ACar(double maxSpeed, int numCylinders) {
super(maxSpeed);
this.numCylinders = numCylinders;
}
void add(){
cars.add(this);
}
public static ArrayList<ACar> getCars(){
return cars;
}
}
class ABoat extends AVehicle {
static ArrayList<ABoat> boats = new ArrayList<ABoat>();
int numRudders;
ABoat(double maxSpeed, int numRudders) {
super(maxSpeed);
this.numRudders = numRudders;
}
void add(){
boats.add(this);
}
public static ArrayList<ABoat> getBoats(){
return boats;
}
}
class APlane extends AVehicle {
static ArrayList<APlane> planes = new ArrayList<APlane>();
int numPropellers;
APlane(double maxSpeed, int numPropellers) {
super(maxSpeed);
this.numPropellers = numPropellers;
}
void add(){
planes.add(this);
}
public static ArrayList<APlane> getPlanes(){
return planes;
}
}
class AVehicleFactory {
public static AVehicle buildVehicle(ABluePrint blueprint) {
AVehicle vehicle;
switch (blueprint.type) {
case 0:
vehicle = new ACar(100.0, 4);
break;
case 1:
vehicle = new ABoat(65.0, 1);
break;
case 2:
vehicle = new APlane(600.0, 2);
break;
default:
vehicle = new AVehicle(0.0);
}
vehicle.add();
return vehicle;
}
}
class ABluePrint {
int type; // 0 = car; // 1 = boat; // 2 = plane;
ABluePrint(int type) {
this.type = type;
}
}
With the above code, the class will have to know about the collection to which it has to be added. This can be considered as a downside to a good design and it can be overcome using the visitor design pattern as demonstrated in the accepted answer (How to avoid 'instanceof' when implementing factory design pattern?).
I know its been a long time since this question was asked. I found http://www.nurkiewicz.com/2013/09/instanceof-operator-and-visitor-pattern.html which looks to be useful. Sharing it here in case if somebody is interested.
Had a similar issue so I used this pattern, to understand it better I created a simple UML drawing showing the sequence of things in comments (follow the numbers). I used Vince Emighs solution above.. The pattern solution is more elegant but can requires some time to truly understand. It requires one interface and one class more then the original but they are very simple.
What if AVehicle classes are out of your control? E.g. you have it from some 3rd party lib? So you have no way to add the Visitor pattern accept() method. Also you could probably dislike boilerplate code in each of the AVehicle subclass and prefer to put everything in one special class keeping your classes clean.
For some cases it could be better just to use HashMap.
In your sample just use:
Map<Class<? extends AVehicle>, List<? extends AVehicle>> lists = new HashMap<>();
lists.put(ACar.class, new ArrayList<ACar>());
lists.put(ABoat.class, new ArrayList<ABoat>());
lists.put(APlane.class, new ArrayList<APlane>());
for (ABluePrint bp : bluePrints) {
AVehicle v = AVehicleFactory.buildVehicle(bp);
allVehicles.add(v);
lists.get(v.getClass()).add(v);
}
The problem with this HashMap approach is that you have to register all possible classes including all known subclasses. Although if you have huge hierarchy and it is not needed all classes for your task you can save lots of work registering in the Map just needed ones.
I'm creating a (atypical)tree in Java that will be composed of three classes: node, branch and leaf
Each node stores the branches it is connected to in a HashSet. The branch is supposed to lead to a descendent node or a leaf, but I'm not sure how to code that. Would I just have two separate variables, one Node and one Leaf in the branch class, along with two sets of getters and setters, even though I will never use both? Is there a best practice in this regard?
I was thinking maybe make node and leaf subclasses of the same superclass, but they have absolutely nothing in common in terms of code(i.e. different variable types, functions, etc.).
EDIT:
Node references branches and
each Branch references a Node or a Leaf
I'd probably go with something like this:
interface BranchDestination {
boolean isLeaf();
}
class Node implements BranchDestination {
private Set branches;
public boolean isLeaf() {
return false;
}
...
}
class Leaf implements BranchDestination {
public boolean isLeaf() {
return true;
}
...
}
class Branch {
BranchDestination destination;
...
}
I do like the idea of defining an interface for the leaf / node classes, and implement that interface in each. I would define a simple function in that interface (syntax might be wrong below, but it's pseduo-ish code):
interface BranchItem {
public object[] GetVals();
}
public class Branch
{
public BranchItem item;
}
public class Leaf implements BranchItem
{
private object myVal = <your data here>;
public object[] GetVals() {
return new object[] { myVal };
}
}
public class Node implements BranchItem
{
private myBranches[] = <List of Branches>;
public object[] GetVals() {
object[] myArray = new object[];
foreach (BranchItem b in myBranches)
{
myArray.addTo(b.item.GetVals());
}
return myArray;
}
}
When traversing your node, simply iterate over the Branches and call GetVals().
The Leaf class will simply returns it's stored value.
The Node Class will recursively loop over it's branches, calling GetVals() on each and add it to it's own returned array.
This is but a simple implementation. If you want sort order, handle collisions or duplicate data, or anything of that nature it could get more complicated.
Make the Leaf class with the basic information.
Make the Branch class which holds references to Leafs.
Make the Node class which holds references to Brahces.
Then try look up Recursion and how to use it to make such constructs :)
Here is my go at it. Though not very elegant, it gets the job done.
Here is the Leaf class:
public class Leaf {
private String text;
public Leaf(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setString(String newString) {
text = newString;
}
#Override
public String toString() {
return text;
}
}
And here is the Branch class:
public class Branch<T> {
private String text;
private HashSet<T> list;
public Branch(String text) {
this.text = text;
list = new HashSet<>();
}
public String getText() {
return text;
}
public void setText(String newText) {
text = newText;
}
public HashSet<T> getHashSet() {
return list;
}
public void setHashSet(HashSet<T> newList) {
list = newList;
}
public String getAllLeaves() {
StringBuilder sb = new StringBuilder();
sb.append(text).append("\n");
for(T t : list) {
sb.append("\t\t");
sb.append(t.toString()).append("\n");
}
return sb.toString();
}
#Override
public String toString() {
return text;
}
}
Lastly the Node class:
public class Node<T> {
private String text;
private HashSet<T> list;
public Node(String text) {
this.text = text;
list = new HashSet<>();
}
public String getText() {
return text;
}
public void setText(String newText) {
text = newText;
}
public HashSet<T> getHashSet() {
return list;
}
public void setHashSet(HashSet<T> newList) {
list = newList;
}
}
Little test program to try it out:
public class TreeConstruct {
public static void main(String[] args) {
Leaf l1 = new Leaf("Leaf 1");
Leaf l2 = new Leaf("Leaf 2");
Leaf l3 = new Leaf("Leaf 3");
Leaf l4 = new Leaf("Leaf 4");
Branch<Leaf> b1 = new Branch("Branch 1");
Branch<Leaf> b2 = new Branch("Branch 2");
Node<Branch> n1 = new Node("Node 1");
b1.getHashSet().add(l1);
b1.getHashSet().add(l2);
b1.getHashSet().add(l3);
b2.getHashSet().add(l4);
n1.getHashSet().add(b1);
n1.getHashSet().add(b2);
System.out.println(printNodeTree(n1));
}
public static String printNodeTree(Node<Branch> n) {
StringBuilder sb = new StringBuilder();
sb.append(n.getText()).append("\n");
for(Branch b : n.getHashSet()) {
sb.append("\t");
sb.append(b.getAllLeaves());
}
return sb.toString();
}
}
The output will be:
Node 1
Branch 1
Leaf 1
Leaf 3
Leaf 2
Branch 2
Leaf 4
Hope this helps!
I have a collection of string paths like ["x1/x2/x3","x1/x2/x4","x1/x5"] in a list.
I need to construct a tree-like structure from this list which can be iterated to get a pretty printed tree.
like this
x1
/ \
x5 x2
/ \
x3 x4
Any ideas/suggestions?
I believe that the problem can be attacked first by processing the list of strings EDIT: The correct answer chosen was an elegant implementation, other suggestions were good too.
Follow an implementation of naive implementation of a visitable tree:
class Tree<T> implements Visitable<T> {
// NB: LinkedHashSet preserves insertion order
private final Set<Tree> children = new LinkedHashSet<Tree>();
private final T data;
Tree(T data) {
this.data = data;
}
void accept(Visitor<T> visitor) {
visitor.visitData(this, data);
for (Tree child : children) {
Visitor<T> childVisitor = visitor.visitTree(child);
child.accept(childVisitor);
}
}
Tree child(T data) {
for (Tree child: children ) {
if (child.data.equals(data)) {
return child;
}
}
return child(new Tree(data));
}
Tree child(Tree<T> child) {
children.add(child);
return child;
}
}
interfaces for Visitor Pattern:
interface Visitor<T> {
Visitor<T> visitTree(Tree<T> tree);
void visitData(Tree<T> parent, T data);
}
interface Visitable<T> {
void accept(Visitor<T> visitor);
}
sample implementation for Visitor Pattern:
class PrintIndentedVisitor implements Visitor<String> {
private final int indent;
PrintIndentedVisitor(int indent) {
this.indent = indent;
}
Visitor<String> visitTree(Tree<String> tree) {
return new IndentVisitor(indent + 2);
}
void visitData(Tree<String> parent, String data) {
for (int i = 0; i < indent; i++) { // TODO: naive implementation
System.out.print(" ");
}
System.out.println(data);
}
}
and finally (!!!) a simple test case:
Tree<String> forest = new Tree<String>("forest");
Tree<String> current = forest;
for (String tree : Arrays.asList("x1/x2/x3", "x1/x2/x4", "x1/x5")) {
Tree<String> root = current;
for (String data : tree.split("/")) {
current = current.child(data);
}
current = root;
}
forest.accept(new PrintIndentedVisitor(0));
output:
forest
x1
x2
x3
x4
x5
Just split each path by its delimiter and then add them to a tree structure one by one.
i.e. if 'x1' does not exist create this node, if it does exist go to it and check if there is a child 'x2' and so on...
I'd make the tree one string at a time.
Make an empty tree (which has a root node - I assume there could be a path like "x7/x8/x9").
Take the first string, add x1 to the root node, then x2 to x1, then x3 to x2.
Take the second string, see that x1 and x2 are already there, add x4 to x2.
Do this for every path you have.
Create an Object Node which contains a parent (Node) and a List of children (Node).
First split the string using ",". For every splitted string you split the string using "/".
Search for the first node identifier (e.g x1) in the root list.
If you can find it, use the node to find the next node identifier (e.g. x2).
If you can not find a node, add the node to the last node you was able to find in the existing lists.
After you have created the list structure, you can print the list to the screen. I would make it recursive.
NOT TESTED, just an animation
public void print(List nodes, int deep) {
if (nodes == null || nodes.isEmpty()) {
return;
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < deep; i++) {
buffer.append("---");
}
for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
Node node = (Node)iterator.next();
System.out.println(buffer.toString() + " " + node.getIdentifier());
print(node.getChildren(), deep + 1);
}
}
public class Menu {
private String path;
private List<Menu> children;
public Menu(String path) {
this.path = path;
children = new ArrayList<>();
}
public void addChild(Menu child) {
children.add(child);
}
public List<Menu> getChildren() {
return children;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Menu getChild(String data) {
for (Menu n : children)
if (n.path.equals(data)) {return n;}
return null;
}
}
Tree builder class:
public class MenuTree {
private Menu root;
public MenuTree() {
root = new Menu("");
}
public void add(String str) {
Menu current = root;
StringTokenizer s = new StringTokenizer(str, "/");
while (s.hasMoreElements()) {
str = (String) s.nextElement();
Menu child = current.getChild(str);
if (child == null) {
current.addChild(new Menu(str));
child = current.getChild(str);
}
current = child;
}
}
public JSONObject toJSON() {
try {
return new JSONObject(new ObjectMapper().writeValueAsString(this.root));
} catch (JsonProcessingException e) {
return null;
}
}
}
Usage:
String slist[] = new String[]{
"mnt/sdcard/folder1/a/b/file1.file",
"mnt/sdcard/folder1/a/b/file2.file",
"D/a/b/c.file",
};
MenuTree t = new MenuTree();
for (String s : slist) {
t.add(s);
}
System.out.println(t.toJSON().toString());
JSONObject result:
{"path":"","children":[{"path":"mnt","children":[{"path":"sdcard","children":[{"path":"folder1","children":[{"path":"a","children":[{"path":"b","children":[{"path":"file1.file","children":[]},{"path":"file2.file","children":[]}]}]}]}]}]},{"path":"D","children":[{"path":"a","children":[{"path":"b","children":[{"path":"c.file","children":[]}]}]}]}]}
Make your tree for every string in array.
Just split path for '/' , check whether the node exists in your tree or not, if it exists then move on... otherwise create a new node and add this node in childrens of parent node.
Iterate using recursion.
Following is model for tree's node.
Class Node{
string name;
List<Node> childrens;
Node(string name){
this.name = name;
this.childrens = new List<Node>();
}
}
This is way how I am doing tree from path (folders) structure. Maybe should help someone with basic logic.
Node:
public class Node {
private String path;
private List<Node> children;
public Node(String path) {
this.path = path;
children = new ArrayList<>();
}
public String getName() {
return getName(path);
}
private String getName(String path) {
String[] split = path.split("\\\\");
return split[split.length - 1];
}
public void addChild(Node child) {
children.add(child);
}
public List<Node> getChildren() {
return children;
}
public String getPath() {
return path;
}
}
FilesTree:
public class FilesTree {
private static final Logger log = Logger.getLogger(FilesTree.class.getName());
private FilesTree() {}
private static void createTree(Node root, List<String> paths) {
for (String path : paths) {
addNode(root, Arrays.asList(path.split("\\\\")), "");
}
}
private static void addNode(Node node, List<String> path, String nodePath) {
if (!path.isEmpty()) {
nodePath = nodePath.equals("") ? path.get(0) : String.format("%s\\%s", nodePath, path.get(0));
}
if (node.getChildren().isEmpty() && path.size() == 1) {
node.addChild(new Node(nodePath));
} else if (!node.getChildren().isEmpty()) {
for (Node actual : node.getChildren()) {
if (actual.getName().equals(path.get(0))) {
addNode(actual, path.subList(1, path.size()), nodePath);
return;
}
}
node.addChild(new Node(nodePath));
} else {
log.info("Without children but with size: " + path.size());
}
}
}