Java - Good way to obtain path in Breadth First Search? - java

I have worked on this the whole day and cannot think of a good solution. I am to implement a breadth first search algorithm in order to solve a sliding puzzle. Here are the relevant parts of my code so far. (I have yet to test if it works since it is incomplete)
So far, this code is expected to traverse through all the possibilities and arrive at the goal. However, I cannot think of a way to record that path from initial to goal state.
private void addToQueue(PuzzleState nextPS) {
if (notVisitedAndNotNull(nextPS))
queue.add(nextPS);
}
private void solveByBFS() {
queue.clear();
queue.add(this.initialState);
long startTime = System.currentTimeMillis();
while(!queue.isEmpty()) { //TODO create a way to backtrack and get a path
if (queue.size() > maxQueueSize)
maxQueueSize = queue.size();
this.currentState = queue.poll();
if (this.currentState.equals(finalState)) { //TODO check if cannot progress any further and terminate
System.out.println("Successful! Ending Time: " + startTime);
return;
}
visited.add(this.currentState);
this.addToQueue(this.currentState.moveUp());
this.addToQueue(this.currentState.moveDown());
this.addToQueue(this.currentState.moveRight());
this.addToQueue(this.currentState.moveLeft());
}
return;
}
So I want a way to back track and get from the goal node to the initial state, reverse the path, and then print it out in a list.
Here is the data structure I am using:
public class SimplePuzzleState implements PuzzleState{
private int rowSz;
private int sz;
private int zeroPos;
private int[] gameState;
#Override
public void configureState(int[] gameState) {
rowSz = (int) Math.sqrt(gameState.length);
sz = gameState.length;
zeroPos = PuzzlePropertyUtility.findZeroPosition(gameState);
this.gameState = gameState;
}
#Override
public PuzzleState moveUp() {
if (zeroPos <= rowSz - 1) {
return null;
}
this.swap(zeroPos, zeroPos - rowSz);
return this.createNewUpdatedState();
}
#Override
public PuzzleState moveDown() {
if (zeroPos >= sz - rowSz) {
return null;
}
this.swap(zeroPos, zeroPos + rowSz);
return this.createNewUpdatedState();
}
#Override
public PuzzleState moveLeft() {
if (zeroPos % rowSz <= 0) {
return null;
}
this.swap(zeroPos, zeroPos - 1);
return this.createNewUpdatedState();
}
#Override
public PuzzleState moveRight() {
if (zeroPos % rowSz >= rowSz -1) {
return null;
}
this.swap(zeroPos, zeroPos + 1);
return this.createNewUpdatedState();
}
#Override
public boolean isEqual(PuzzleState other) {
if (other != null) {
if (this.getStateArray() instanceof int[] && other.getStateArray() instanceof int[])
return (Arrays.equals(this.getStateArray(), other.getStateArray()));
}
return false;
}
#Override
public int[] getStateArray() {
return gameState;
}
private void swap(int pos1, int pos2) {
int temp = this.gameState[pos1];
this.gameState[pos1] = this.gameState[pos2];
this.gameState[pos2] = temp;
}
private PuzzleState createNewUpdatedState() {
PuzzleState newState = new SimplePuzzleState();
newState.configureState(this.getStateArray());
return newState;
}
}
Here is the PuzzleState Interface:
public interface PuzzleState {
public void configureState(int[] gameState);
PuzzleState moveUp();
PuzzleState moveDown();
PuzzleState moveLeft();
PuzzleState moveRight();
boolean isEqual(PuzzleState other);
int[] getStateArray();
}
I have thought about adding an attribute to SimplePuzzleState to include a parent node.
However, I cannot modify the interface which it implements since my instructor does not allow that. Therefore, I cannot backtrack using a linked list method. Are there any smart ways to record the correct path? In the end, my instructor wants me to print a list containing enums which represent the movements. So I have to figure how to map the enums to functions moveUp, moveDown etc.
Thank you in advance. I apologize for posting so much code, but I really need advice on which direction I should take.

You have the right idea. If you can't add parent pointers to the states, then just maintain a HashMap with the same information called something like previous. When you create the four
child states, add mappings from the parent to these four.
// A map to hold parent relations.
HashMap<SimplePuzzleState, SimplePuzzleState> previous = new HashMap<>();
...
// Now change the add function.
private void addToQueue(PuzzleState parentPS, PuzzleState nextPS) {
if (notVisitedAndNotNull(nextPS)) {
queue.add(nextPS);
previous.add(nextPS, parentPS);
nextPS.updateParent(this); // and update where we got from
}
}
// Then update the calls to match:
this.addToQueue(currentState, this.currentState.moveUp());
...
When you find the goal, trace back to the start using the hash just as you would the parent pointers.
if (this.currentState.equals(finalState)) {
System.out.println("Successful! Ending Time: " + startTime);
System.out.println("Path back to start:");
PuzzleState state = currentState;
do {
state.print();
state = previous.get(state);
} while (state != null);
}

Add to SimplePuzzleState another field called gotHereFrom and when you call addToQueue() update this field (per each item). When you're done, instead if printing "successful" and return; start iterating back according to gotHereFrom and print the nodes all the way back:
public class SimplePuzzleState implements PuzzleState{
private int rowSz;
private int sz;
private int zeroPos;
private int[] gameState;
private SimplePuzzleState gotHereFrom; // add this guy
...
protected void updateParent(SimplePuzzleState gotHereFrom) {
this.gotHereFrom = gotHereFrom;
}
...
}
and:
private void addToQueue(PuzzleState nextPS) {
if (notVisitedAndNotNull(nextPS)) {
queue.add(nextPS);
nextPS.updateParent(this); // and update where we got from
}
}
iterating the results:
...
if (this.currentState.equals(finalState)) { //TODO check if cannot progress any further and terminate
System.out.println("Successful! Ending Time: " + startTime);
String path = "";
while (gotHereFrom != null) {
path += " -> " + gotHereFrom;
gotHereFrom = gotHereFrom.getGotHereFrom();
}
System.out.println(path);
return;
}

Related

Which Object Oriented design is a better pick when one subclass calls another?

In my scenario, we offer multiple plans to customers. (planA, planB, planC etc.) planA is lower than planB and planB is lower than planC. A customer can move from lower plan to higher plan but not vice-versa. If a customer is on planA and wants to 'activate' planB, then planA must be cancelled. Essentially, a plan can be 'activated' and 'deactivated'. I had 2 designs in mind.
interface Plan {
activate();
deactivate();
}
This interface will be inherited by each plans' (planA, planB, planC, etc). The activate method would be inherited and look something like this:
activate() {
Plan planToCancel = getLowerGradePlanToCancel()
planToCancel.cancel();
// perform business logic to activate plan.
}
Option B is something similar to strategy pattern: I have 2 interfaces:
interface Activate {
activate();
}
interface Deactivate {
deactivate()
}
Each of the plans will inherit those interfaces. Then my business logic would look something like this:
activatePlan(planName, planToDeactivate) {
Activate activate = Factory.getActivateInstanceForPlan(planName);
DeActivate dectivate = Factory.getActivateInstanceForPlan(planToDeactivate);
deactivate.deactivate();
activate.activate();
}
Of the two designs which one is more appropriate (Object Oriented) and why ? The only thing in code that is likely to change is more plans will be added in future.
You have 3 plans. Plan C can't go higher and similarly plan A can't go lower. Plan B can do both operations. Use one interface and put activate and deactivate methods there. You already mentioned that on option A. Use template pattern there to give an opportunity to change their behaviours for your plans. This will be appropriate if you will add another plans later on. This will help you a lot when you add another plans.
If you will have only three plans, then second option is more appropriate. Since you have only 3 plans and only one of them using activate and deactivate together, then you don't need to implement both of the methods, interfaces. This will decrease the dependencies of your code.
Pick the best choice for your case.
I have a different approach in mind where you have a class that manages all the plans, while plan interface is encapsulated and only reveals the necessary of its API.
I think this approach will have minimal code modification for each added Plan, moreover, it can prevent user from making mistakes (e.g. downgrading a plan).
The essential interfaces:
interface Plan {
public Plan next();
public boolean isActivated();
// for debug purposes
public String planDescription();
}
interface PlansManager {
public Plan nextPlan(Plan current);
}
The basic idea is to have some SemiConcretePlan class which implements the static (mutual) behaviour in all plans, the public API is next & isActivated while activate and cancel methods private (you don't want the user to cancel a plan without switching to the next or to activated a cancelled one be keeping a previous Plan pointer on it) and only the PlansManager or the Plan itself will handle the activation and cancellation, PlansManager activates the first plan and returns it and next method uses PlansManager to get the next and only the SemiConcertePlan activate the current and cancels the previous Plan.
Here the SemiConcertePlan:
abstract class SemiConcretePlan implements Plan {
private PlansManager m_plansManager;
private boolean m_isActivated;
private int m_id;
private static int s_idGenerator = 0, s_firstActivatedId = 1;
public SemiConcretePlan(PlansManager plansManager){
m_plansManager = plansManager;
m_id = generateId();
m_isActivated = (m_id == s_firstActivatedId);
}
private int generateId() {
return ++s_idGenerator;
}
private void activatePlan() {
this.m_isActivated = true;
}
private void cancelPlan() {
this.m_isActivated = false;
}
public boolean isActivated() {
return this.m_isActivated;
}
public Plan next() {
this.cancelPlan();
SemiConcretePlan nextPlan = (SemiConcretePlan) m_plansManager.nextPlan(this);
nextPlan.activatePlan();
return nextPlan;
}
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || !(other instanceof SemiConcretePlan) || this.hashCode() != other.hashCode())
return false;
SemiConcretePlan otherPlan = ((SemiConcretePlan) other);
if (m_id != ((SemiConcretePlan) otherPlan).m_id)
return false;
return true;
}
public abstract int hashCode();
public abstract String planDescription();
}
planDescription method is an example of dynamic method, hashCode is needed for class PlansManager to hash plans in map which map current plan to higher (next) plan.
Here is the AscedingPlansManager class:
class AscedingPlansManager implements PlansManager{
private List<Plan> m_plansList;
private Map<Plan, Plan> m_planToHigherPlanMapping;
public AscedingPlansManager() {
m_plansList = new LinkedList();
m_planToHigherPlanMapping = new HashMap();
Plan[] plans = {
new PlanA(this),
new PlanB(this),
new PlanC(this),
new PlanD(this)
};
for(int i = 0; i < plans.length - 1; ++i) {
m_plansList.add(plans[i]);
m_planToHigherPlanMapping.put(plans[i], plans[i+1]);
}
m_plansList.add(plans[plans.length - 1]);
m_planToHigherPlanMapping.put(plans[plans.length - 1], plans[plans.length - 1]);
}
public Plan nextPlan(Plan current) {
return m_planToHigherPlanMapping.getOrDefault(current, null);
}
private void activatePlan(Plan plan) {
try {
Method privateActivateMethod = SemiConcretePlan.class.getDeclaredMethod("activatePlan");
privateActivateMethod.setAccessible(true);
privateActivateMethod.invoke(plan);
} catch(Exception e) {
e.printStackTrace();
}
}
public void cancelAll() {
for(Plan plan: m_plansList)
try {
Method privateActivateMethod = SemiConcretePlan.class.getDeclaredMethod("cancelPlan");
privateActivateMethod.setAccessible(true);
privateActivateMethod.invoke(plan);
} catch(Exception e) {
e.printStackTrace();
}
}
public Plan firstPlan() {
Plan first = m_plansList.get(0);
this.activatePlan(first);
return first;
}
public boolean[] plansToActivationState() {
boolean[] ret = new boolean[m_plansList.size()];
int index = 0;
for(Plan plan: m_plansList)
ret[index++] = plan.isActivated();
return ret;
}
}
I know that this is huge code, but I think it will make add plans easy, you will only need to change the hashCode method, the sequence of the plans can be changed in the constructor of AscedingPlansManager or creating a different manger class from scratch.
Here is the full code, you can see how little changes I needed to do for class PlanD:
import java.util.;
import java.lang.reflect.;
interface Plan {
public Plan next();
public boolean isActivated();
// for debug purposes
public String planDescription();
}
interface PlansManager {
public Plan nextPlan(Plan current);
}
abstract class SemiConcretePlan implements Plan {
private PlansManager m_plansManager;
private boolean m_isActivated;
private int m_id;
private static int s_idGenerator = 0, s_firstActivatedId = 1;
public SemiConcretePlan(PlansManager plansManager){
m_plansManager = plansManager;
m_id = generateId();
m_isActivated = (m_id == s_firstActivatedId);
}
private int generateId() {
return ++s_idGenerator;
}
private void activatePlan() {
this.m_isActivated = true;
}
private void cancelPlan() {
this.m_isActivated = false;
}
public boolean isActivated() {
return this.m_isActivated;
}
public Plan next() {
this.cancelPlan();
SemiConcretePlan nextPlan = (SemiConcretePlan) m_plansManager.nextPlan(this);
nextPlan.activatePlan();
return nextPlan;
}
public boolean equals(Object other) {
if (this == other)
return true;
if (other == null || !(other instanceof SemiConcretePlan) || this.hashCode() != other.hashCode())
return false;
SemiConcretePlan otherPlan = ((SemiConcretePlan) other);
if (m_id != ((SemiConcretePlan) otherPlan).m_id)
return false;
return true;
}
public abstract int hashCode();
public abstract String planDescription();
}
class AscedingPlansManager implements PlansManager{
private List<Plan> m_plansList;
private Map<Plan, Plan> m_planToHigherPlanMapping;
public AscedingPlansManager() {
m_plansList = new LinkedList();
m_planToHigherPlanMapping = new HashMap();
Plan[] plans = {
new PlanA(this),
new PlanB(this),
new PlanC(this),
new PlanD(this)
};
for(int i = 0; i < plans.length - 1; ++i) {
m_plansList.add(plans[i]);
m_planToHigherPlanMapping.put(plans[i], plans[i+1]);
}
m_plansList.add(plans[plans.length - 1]);
m_planToHigherPlanMapping.put(plans[plans.length - 1], plans[plans.length - 1]);
}
public Plan nextPlan(Plan current) {
return m_planToHigherPlanMapping.getOrDefault(current, null);
}
private void activatePlan(Plan plan) {
try {
Method privateActivateMethod = SemiConcretePlan.class.getDeclaredMethod("activatePlan");
privateActivateMethod.setAccessible(true);
privateActivateMethod.invoke(plan);
} catch(Exception e) {
e.printStackTrace();
}
}
public void cancelAll() {
for(Plan plan: m_plansList)
try {
Method privateActivateMethod = SemiConcretePlan.class.getDeclaredMethod("cancelPlan");
privateActivateMethod.setAccessible(true);
privateActivateMethod.invoke(plan);
} catch(Exception e) {
e.printStackTrace();
}
}
public Plan firstPlan() {
Plan first = m_plansList.get(0);
this.activatePlan(first);
return first;
}
public boolean[] plansToActivationState() {
boolean[] ret = new boolean[m_plansList.size()];
int index = 0;
for(Plan plan: m_plansList)
ret[index++] = plan.isActivated();
return ret;
}
}
class PlanA extends SemiConcretePlan {
public PlanA(PlansManager plansManager) {
super(plansManager);
}
public int hashCode() {
return 1;
}
public String planDescription() {
return "This is PlanA";
}
}
class PlanB extends SemiConcretePlan {
public PlanB(PlansManager plansManager) {
super(plansManager);
}
public int hashCode() {
return 2;
}
public String planDescription() {
return "This is PlanB";
}
}
class PlanC extends SemiConcretePlan {
public PlanC(PlansManager plansManager) {
super(plansManager);
}
public int hashCode() {
return 3;
}
public String planDescription() {
return "This is PlanC";
}
}
class PlanD extends SemiConcretePlan {
public PlanD(PlansManager plansManager) {
super(plansManager);
}
public int hashCode() {
return 4;
}
public String planDescription() {
return "This is PlanD";
}
}
public class Main{
public static void main(String []args){
AscedingPlansManager ascedingPlansManager = new AscedingPlansManager();
Plan currentPlan = ascedingPlansManager.firstPlan();
int i = 0, maxIterations = 5;
while((++i) <= maxIterations) {
System.out.println(currentPlan.planDescription());
System.out.println(Arrays.toString(ascedingPlansManager.plansToActivationState()));
currentPlan = currentPlan.next();
}
ascedingPlansManager.cancelAll();
System.out.println("After canceling all plans");
System.out.println(Arrays.toString(ascedingPlansManager.plansToActivationState()));
}
}
I still not sure of my implementation, I usually access private method in c++ with friend modifier, if you want to discuss anything feel free to do so.

How do I compare the value of an Enum with all possible values of the Enum in an Enum method and avoid missing return statement?

I'm just learning about enumerations in Java. When I run the code below I get an error which I also reproduce below. Basically, my question is: when I define a method in an Enum, and in that method I want to check the value of the enum so that I can do something based on that value, how do I perform this check?
Below I have an Enum with three possible values, and in the method getNext, I have three if statements comparing the value of this Enum with each of the three possible values. But I still get an error saying that there is a path without a return.
package enumerations;
enum TrafficLightColor2 {
RED(12), GREEN(10), YELLOW(2);
private int waitTime;
TrafficLightColor2(int waitTime) {
this.waitTime = waitTime;
}
int getWaitTime() {
return waitTime;
}
TrafficLightColor2 getNext() {
if (this.equals(TrafficLightColor2.GREEN)) {
return TrafficLightColor2.YELLOW;
}
if (this.equals(TrafficLightColor2.YELLOW)) {
return TrafficLightColor2.RED;
}
if (this.equals(TrafficLightColor2.RED)) {
return TrafficLightColor2.GREEN;
}
}
}
// A computerized traffic light.
class TrafficLightSimulator2 implements Runnable {
private Thread thrd; // holds the thread that runs the simulation
private TrafficLightColor2 tlc; // holds the traffic light color
boolean stop = false; // set to true to stop the simulation
boolean changed = false; // true when the light has changed
TrafficLightSimulator2(TrafficLightColor2 init) {
tlc = init;
thrd = new Thread(this);
thrd.start();
}
TrafficLightSimulator2() {
tlc = TrafficLightColor2.RED;
thrd = new Thread(this);
thrd.start();
}
// Start up the light.
public void run() {
while (!stop) {
try {
Thread.sleep(tlc.getWaitTime());
} catch (InterruptedException exc) {
System.out.println(exc);
}
changeColor();
}
}
// Change color.
synchronized void changeColor() {
tlc = tlc.getNext();
changed = true;
notify(); // signal that the light has changed
}
// Wait until a light change occurs.
synchronized void waitForChange() {
try {
while (!changed)
wait(); // wait for light to change
changed = false;
} catch (InterruptedException exc) {
System.out.println(exc);
}
}
// Return current color.
synchronized TrafficLightColor2 getColor() {
return tlc;
}
// Stop the traffic light.
synchronized void cancel() {
stop = true;
}
}
class TrafficLightDemo2 {
public static void main(String args[]) {
TrafficLightSimulator tl =
new TrafficLightSimulator(TrafficLightColor.GREEN);
for (int i = 0; i < 9; i++) {
System.out.println(tl.getColor());
tl.waitForChange();
}
tl.cancel();
}
}
I get the error
$ javac enumerations/TrafficLightDemo2.java
enumerations/TrafficLightDemo2.java:26: error: missing return statement
}
^
1 error
TrafficLightColor2 getNext() {
if (this.equals(TrafficLightColor2.GREEN)) {
return TrafficLightColor2.YELLOW;
}
if (this.equals(TrafficLightColor2.YELLOW)) {
return TrafficLightColor2.RED;
}
if (this.equals(TrafficLightColor2.RED)) {
return TrafficLightColor2.GREEN;
}
}
This method doesn't return the value if all 3 if are false.
Add return at the and or better throw an error, e.g.
throw new IllegalArgumentException("Unsupported enum")
The advantage of using instance fields in enum classes is that you can associate implementation details easily with your constants that are independent from your API. In other words, you can easily associate data with your enum constants that would admit an elegant solution that you aren't forever married to in the case that, for example, you need to add a new enum constant.
So, you can greatly simplify your implementation while fulfilling the same contract as follows:
enum TrafficLightColor2 {
RED(2, 12),
GREEN(0, 10),
YELLOW(1, 2);
private int order; // implementation detail; non-exported
private int waitTime;
TrafficLightColor2(int ord, int waitTime) {
this.order = ord;
this.waitTime = waitTime;
}
int getWaitTime() {
return waitTime;
}
TrafficLightColor2 getNext() {
final int nextColor = (this.order + 1) % 3; // magic numbers introduce fragility
return Arrays.stream(TrafficLight2.values())
.filter(e -> e.order == nextColor)
.findAny()
.get();
}
}
This version has some advantages to your original implementation: it is easier to maintain since, if enum constants are added, the compiler will force you to add an order value. In the original, if you forgot to modify your if-else-block after adding a constant, your program would continue to work but it would not provide the correct behavior. And because the implementation of the order is hidden, you are free to remove it or change it to some other implementation at any time without affecting the correctness of your API.
Have you considered including the next state along with the declared values?
public enum TrafficLightColor2 {
RED(12, "GREEN"), GREEN(10, "YELLOW"), YELLOW(2, "RED");
int waitTime;
String nextState;
Configurations(int waitTime, String nextState) {
this.waitTime = waitTime;
this.nextState = nextState;
}
public int getWaitTime() {
return waitTime;
}
public String getNextState() {
return nextState;
}
}
With this you can get the next state as
TrafficLightColor2 trafficLightColor = TrafficLightColor2.GREEN;
System.out.println(TrafficLightColor2.valueOf(trafficLightColor.getNextState()));

How to update multiple instances of a class at once in Java

I'm writing a game-like program and it has a class that has to act as an item. Normally I would just keep it as an item but every one has to wait 10 game-days in order to start doing what it's meant to. Is there a way to update the days in all the classes at once? I've tried to use a static method but you can't use instance variables in those so it didn't work. I've thought about possibly making a code that expands every time a new instance is made but I can't find anything i can understand about it. Is there any way to add to a method, make this an item, anything? This is what I have at the moment:
public class Tree
{
private boolean fullGrown;
private int day;
private int APDay; //apples per day
private static int totalApples;
public Tree()
{
fullGrown = false;
day = 0;
APDay = (int) (Math.random()*2) + 4;
}
public void updateDay()
{
day = day + 1;
if (day == 10) fullGrown = true;
if (fullGrown == true) totalApples = totalApples + APDay;
}
public void skipGrowth()
{
fullGrown = true;
}
}
Although this works, you have to update the day for every instance separately. I need a way to update all the instances at the same time. This will also be used by a code and not the actual interface, just in case that's helpful.
Observer and factory pattern looks like a good candidate here.
I hope the code below explain rest to you
public interface DayEventListener {
public void onDay10(DayEvent DayEvent);
}
public class DayEvent {
//... pojo
}
public class AwesomeGame {
private List<DayEventListener> dayEventListenerList = new ArrayList<>();
public void addDayListener(DayEventListener del) {
dayEventListener.add(del);
}
public void fireDay10Event(DayEvent de) {
for(DayEventListener del : dayEventListenerList) {
del.onDay10(de);
}
}
public class Item implements DayEventListener {
//All constructors should be private
public static Item buildItem() {
Item Item = new Item();
awesomeGame.addDayEventListener(Item);
return item;
}
}
so I did some research and while I was working on another project I discovered that i could use a vector to keep track of all my instances, so here is that class:
import java.util.Vector;
public class catcher
{
private static Vector allInstances = new Vector();
private int catchLeft;
private String name;
public catcher(String name)
{
catchLeft = Integer.parseInt(name.substring(name.indexOf("#") + 1, name.length()));
catchLeft--;
this.name = name;
if (catchLeft != 0) allInstances.add(this);
}
public static synchronized Vector getAllInstances()
{
return (Vector) (allInstances.clone());
}
public boolean check(String name, boolean change)
{
boolean foo;
if (this.name.equals(name))
{
if (change == true) catchLeft--;
foo = true;
}
else foo = false;
if (catchLeft <= 0) this.finalize();
return foo;
}
public void finalize()
{
allInstances.removeElement(this);
}
public static void clear()
{
allInstances.clear();
}
}
now that I have a record of all the instances, I used this method in another class to assess all the instances:
import java.util.Iterator;
import java.util.Vector;
public class recipe
{
private boolean checkForList(String name, boolean add)
{
Iterator list = catcher.getAllInstances().iterator();
boolean running = true;
boolean booleanReturn = true;
while (running == true)
{
if (list.hasNext())
{
catcher Foo = (catcher) (list.next());
if (Foo.check(name, false) == true)
{
Foo.check(name, true);
running = false;
booleanReturn = true;
}
}
else
{
if (add == true) new catcher(name);
running = false;
booleanReturn = false;
}
}
return booleanReturn;
}
}
I'm sure that this can be modified to update the classes instead of just accessing them.

Trouble casting an interface to an implemented class

Here is my class:
public class LinkedListSet implements Set {
private class Node //much easier as a private class; don't have to extend
{
private int data;
private Node next;
public Node (){}
public Node (int x)
{
data = x;
}
public int data()
{
return data;
}
public Node next()
{
return next;
}
}
private Node first;
private int Size;
private int whichList; //used to identify the particular LL object
Here is my interface:
public interface Set {
public boolean isEmpty();
public void makeEmpty();
public boolean isMember(int x);
public void add(int x);
public void remove(int y);
public void union(Set other, Set result);
public void intersection (Set other, Set result);
public void difference (Set other, Set result);
#Override
public String toString();
#Override
public boolean equals(Object other);
public void setList(int i); //i added this to use it as an identifier for each
//list element in the set array
public String getListId(); //these two extra methods make life easier
}
I have a method like this (in the LinkedListSet class):
public void difference (Set other, Set result)
{
if (other.isEmpty())
{
System.out.println("The set is empty before cast");
}
LinkedListSet othr = (LinkedListSet) other;
LinkedListSet res = (LinkedListSet) result;
if (this.isEmpty() || othr.isEmpty())
{
if (othr.isEmpty())
System.out.println("The set is empty after cast");
if (this.isEmpty())
System.out.println("This is also empty");
return;
}
differenceHelper(this.first, othr.first, res);
result = res;
}// the print statements were added for debugging
The problem is, in the above method I am unable to cast the Set Other into its linked list implementation. When I call this method in the main program, the parameter is actually of type linked list (so I don't get any errors obviously).
However, all the instance variables are null. The list is empty before and after I cast it (when it actually isn't empty). I know this is because the interface doesn't include any information about the Nodes, but is there anything I can do other than editing the interface to incorporate the Node?
I hope I've made this clear enough. Any help would be appreciated.
edit:
In the main program I created an array of Sets.
Set[] sets = new Set[7];
for (int i = 0; i< sets.length; i++) //initialize each element
{
sets[i] = new LinkedListSet();
}
each list has nodes with data values which are added on later on in the code...
then I call the difference method.
sets[0].difference(sets[1], sets[4])
sets[1].isEmpty returns true for some reason (even though it is not).
If I were to do something like:
System.out.println(sets[1].first.data()) I would have no problem whatsoever.
For some reason all the values become null when the parameters are passed to the difference method.
public boolean isEmpty()
{
return first == null;
}
I tested what you are trying to do with the following code and I see no problems:
import org.junit.Test;
public class RandomCastTest {
public interface Set {
boolean isEmpty();
void add(int x);
void difference(Set other, Set result);
#Override
String toString();
#Override
boolean equals(Object other);
}
public class LinkedListSet implements Set {
private class Node //much easier as a private class; don't have to extend
{
private int data;
private Node next;
public Node() {
}
public Node(int x) {
data = x;
}
public int data() {
return data;
}
public Node next() {
return next;
}
public void next(Node node) {
next = node;
}
}
private Node first;
private int Size;
private int whichList; //used to identify the particular LL object
#Override
public boolean isEmpty() {
return first == null;
}
#Override
public void add(int x) {
Node node = new Node(x);
if (first == null) {
first = node;
} else {
Node currentNode;
Node nextNode = first;
do {
currentNode = nextNode;
nextNode = currentNode.next();
} while (nextNode != null);
currentNode.next(node);
}
Size++;
}
#Override
public void difference(Set other, Set result) {
if (other.isEmpty()) {
System.out.println("The set is empty before cast");
}
LinkedListSet othr = (LinkedListSet) other;
LinkedListSet res = (LinkedListSet) result;
if (this.isEmpty() || othr.isEmpty()) {
if (othr.isEmpty())
System.out.println("The set is empty after cast");
if (this.isEmpty())
System.out.println("This is also empty");
return;
}
result = res;
}
}
#Test
public void test() {
Set[] sets = new Set[7];
for (int i = 0; i < sets.length; i++) {
sets[i] = new LinkedListSet();
}
for (int i = 0; i < 5; i++) {
sets[1].add(i);
}
for (int i = 5; i < 10; i++) {
sets[0].add(i);
}
sets[0].difference(sets[1], sets[4]);
// ... find difference
}
}
To simplify I removed unimplemented methods from the interface. Also added the add method implementation. Please see if it works for you.

HashMap and ArrayList order

I have HashMap and ArrayList I am adding data wih following code:
conversationsMap.put(sendName,new Conversation(receiverName,currentTime));
conversationsList=new ArrayList<Conversation>(conversationsMap.values());
I have an method for get currentTime like this:
conversation.getTime();
I want to order conversationsList by currentTime with this code they are not ordering.conversationsList should be like this:
1)currentTime:10
2)currentTime:9
2)currentTime:8
...
How can i achive this ? I guess I need to use a loop for get values then add to conversationsList
private class CustomComparator<T extends Conversation> implements Comparator<Conversation>{
public int compare(Conversation loBean1, Conversation loBean2) {
if(obj1.getTime()<obj2.getTime()) {
return -1;
} else if(obj1.getTime()>obj2.getTime()) {
return 1;
} else {
return 0
}
}
}
Collections.sort(conversationsList, new CustomComparator<Conversation>());
You can also implement the Comparable Interface.. And do something like this.
public class Conversation implements Comparable<Conversation>
{
int currentTime;
public int getCurrentTime()
{
return currentTime;
}
public void setCurrentTime(int currentTime)
{
this.currentTime = currentTime;
}
#Override
public int compareTo(Conversation o)
{
int ret = 0;
if (this.currentTime > o.getCurrentTime())
{
ret = 1;
}
else if (this.currentTime < o.getCurrentTime())
{
ret = -1;
}
return ret;
}
}
if you need to use it in one place then you may create the comparator on fly
conversationsMap.put(sendName,new Conversation(receiverName,currentTime));
conversationsList=new ArrayList<Conversation>(conversationsMap.values());
Collections.sort(conversationsList, new Comparator<Conversation>()
{
#Override
public int compare(Conversation obj1, Conversation obj2)
{
if(obj1.getTime()<obj2.getTime()) {
return -1;
} else if(obj1.getTime()>obj2.getTime()) {
return 1;
} else {
return 0
}
}
});
which is some time convenient for small task. but if you are writing big project and long time code maintaining is there. you might use the previous answer provided.
for quick solution:

Categories

Resources