Suppose I have a Point class with fields x,y,z,name.
Objects of this class must be inserted in a Hash Set in two different ways depending on the user choice:
equals() checks equality of x,y,z fields
equals() checks equality of x,y,z,name fields
So I wonder what is the better way to organize such equals() redefinition on the fly during program execution?
You can create 2 Classes: Point and NamedPoint and override the equals() and hashcode() methods.
Here is an example in pseudo code:
class Point{
String name
int x,y,z
equals{
...
}
hashCode{
...
}
}
class NamedPoint extends Point{
equals{
}
hashCode{
}
}
Another option is to use one class, but add a new boolean switch, which changes the behavior of equals and hashCode.
P.S. I recommend you to read What issues should be considered when overriding equals and hashCode in Java?. You must be careful overriding these methods. It is useful to use the eclipse feature "Source --> Generate hashCode() and equals().." and after that to change the behavior of the generated methods.
P.S.2: Grigory Kalabin's link describes, what are the problems that might occure doing this.
If you can change from using HashSet to a TreeSet and add a custom comparator:
public class Point implements Comparable<Point> {
private double x;
private double y;
private double z;
private String name;
public Point( final double x, final double y, final double z, final String name ) {
setX( x );
setY( y );
setZ( z );
setName( name );
}
public boolean equals( final Point point ){
final boolean isEqual =
( this.getX() == point.getX()
&& this.getY() == point.getY()
&& this.getZ() == point.getZ() )
|| ( this.getName().equals( point.getName() ) );
// System.out.println( this.toString() + " == " + point.toString() + " = " + isEqual );
return isEqual;
}
/// #return the x
public double getX() { return x; }
/// #return the y
public double getY() { return y; }
/// #return the z
public double getZ() { return z; }
/// #return the name
public String getName() { return name; }
/// #param x the x to set
public void setX(final double x) { this.x = x; }
/// #param y the y to set
public void setY(final double y) { this.y = y; }
/// #param z the z to set
public void setZ(final double z) { this.z = z; }
/// #param name the name to set
public void setName(final String name) { this.name = name; }
public String toString() {
final StringBuffer str = new StringBuffer();
str.append( '(' );
str.append( getX() );
str.append( ',' );
str.append( getY() );
str.append( ',' );
str.append( getZ() );
str.append( ',' );
str.append( getName() );
str.append( ')' );
return str.toString();
}
public double distanceFromOriginSquared(){
return this.getX()*this.getX()
+ this.getY()*this.getY()
+ this.getZ()*this.getZ();
}
#Override
public int compareTo( final Point point ) {
if ( this.getName().equals( point.getName() ) )
return 0;
final double td = this.distanceFromOriginSquared();
final double pd = point.distanceFromOriginSquared();
if ( td < pd ) return -1;
if ( td > pd ) return +1;
if ( this.getX() < point.getX() ) return -1;
if ( this.getX() > point.getX() ) return +1;
if ( this.getY() < point.getY() ) return -1;
if ( this.getY() > point.getY() ) return +1;
return 0;
}
}
Running this:
public static void main( final String[] args ){
Point[] pts = {
new Point( 1, 1, 1, "1" ),
new Point( 2, 2, 2, "2" ),
new Point( 3, 3, 3, "3" ),
new Point( 1, 1, 1, "4" ),
new Point( 4, 4, 4, "2" )
};
TreeSet<Point> ps = new TreeSet<Point>();
for ( Point p : pts )
ps.add( p );
System.out.println( ps );
}
Gives an output of
[(1.0,1.0,1.0,1), (2.0,2.0,2.0,2), (3.0,3.0,3.0,3)]
So the last two values are not entered into the TreeSet as they are rejected by the comparator.
Related
I have a class PointDensity that is implemented as:
import java.sql.Date;
public class PointDensity {
private int id_place;
private String algorithm;
private Date mission_date;
private int mission_hour;
private int x;
private int y;
public PointDensity(int id_place, String algorithm, Date mission_date, int mission_hour, int x, int y) {
this.id_place = id_place;
this.algorithm = algorithm;
this.mission_date = mission_date;
this.mission_hour = mission_hour;
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object obj){
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PointDensity other = (PointDensity) obj;
return id_place == other.id_place
&& algorithm.equals(other.algorithm)
&& mission_date.equals(other.mission_date)
&& mission_hour == other.mission_hour
&& x == other.x
&& y== other.y;
}
#Override
public int hashCode(){
final int prime = 31;
int result = 1;
result = prime * result + y;
result = prime * result + ((algorithm == null) ? 0 : algorithm.hashCode());
result = prime * result + x;
result = prime * result + ((mission_date == null) ? 0 : mission_date.toString().hashCode());
result = prime * result + mission_hour;
result = prime * result + id_place;
return result;
}
}
I read some stuff and get values from a database. And then I want to use a HashMap() in order to store a PointDensity object as key and the times it has been encountered as a value. However, it never finds that the object is the same.
Map<PointDensity, Integer> pointDensities = new HashMap<>();
while (resultSet.next()){
PointDensity pointDensity =
new PointDensity(
resultSet.getInt(1),
resultSet.getString(2),
new Date(timestampValues.getLong(i)),
new java.util.Date(timestampValues.getLong(i)).getHours(),
xValues.getInt(i),
yValues.getInt(i)
);
if (pointDensities.containsKey(pointDensity)){
//IT NEVER ENTERS HERE!!!
System.out.println("exists");
int times = pointDensities.get(pointDensity);
pointDensities.replace(pointDensity, times++);
}else{
pointDensities.put(pointDensity, 1);
}
}
Thanks in advance :)
The following code works for me, your hashcode and equals methods seem OK. The error must be in code you aren't showing us, or in the database data itself.
public static void main( String[] args ) {
Map<PointDensity, Integer> pointDensities = new HashMap<>();
PointDensity pointDensity = new PointDensity( 10, "TEST",
new Date( 3, 1, 2019 ), new java.util.Date().getHours(),
42, 24 );
pointDensities.put( pointDensity, 1 );
System.out.println( "pointDensity equal to self:"
+ pointDensity.equals( pointDensity ) );
if( pointDensities.containsKey( pointDensity ) ) {
//IT NEVER ENTERS HERE!!!
System.out.println( "exists" );
int times = pointDensities.get( pointDensity );
pointDensities.replace( pointDensity, times++ );
} else {
pointDensities.put( pointDensity, 1 );
}
}
}
Output:
run:
pointDensity equal to self:true
exists
BUILD SUCCESSFUL (total time: 0 seconds)
I'm trying to print out locations of center dots. Compared dots must be in radius of 16. Printing out only if there is more than 5 dots in one place calculating from center.
Center dot is, which is nearest to all nearby dots
My code is giving me false positives and duplicates. Methods:
HashMap<Location, HashSet<Location>> map = new HashMap<Location, HashSet<Location>>();
for (LocationCopy loc : locs) {
HashSet<LocationCopy> locsCopy = new HashSet<LocationCopy>(locs);
locsCopy.remove(loc);
for (LocationCopy loc2 : locsCopy) {
if (distance(loc2.getX(),loc.getX(),loc2.getZ(),loc.getZ()) <= 16) {
if (!map.containsKey(loc.getLoc())) {
HashSet<Location> hs = new HashSet<Location>();
hs.add(loc2.getLoc());
map.put(loc2.getLoc(), hs);
} else {
HashSet<Location> hs = map.get(loc.getLoc());
hs.add(loc2.getLoc());
map.put(loc2.getLoc(), hs);
}
}
}
}
for (Location loc : map.keySet()) {
if (map.get(loc).size() > 5) {
write("More than " + map.get(loc).size() + locToString(loc) + ": " + getLocs(map.get(loc)) + "<br>", fileName, beta);
}
}
private double distance(double x1, double x2, double z1, double z2){
return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(z2-z1,2));
}
Class:
public class LocationCopy {
private int x, y, z;
private String world;
public LocationCopy(int x, int y, int z, String world) {
this.x = x;
this.y = y;
this.z = z;
this.world = world;
}
public LocationCopy(Location spawner) {
this.x = spawner.getBlockX();
this.y = spawner.getBlockY();
this.z = spawner.getBlockZ();
this.world = spawner.getWorld().getName();
}
public int getX(){
return x;
}
public int getZ(){
return z;
}
public Location getLoc() {
return new Location(Bukkit.getWorld(world), x, y, z);
}
}
There are serval small problems in your code:
map.put(loc2.getLoc(), hs); should be map.put(loc.getLoc(), hs); instead
You need to add a hashCode method to your classes, because otherwhise the HashSets you use will not be able to identify objects that represent the same location
You only search for groups of points, not for their centers
A solution could look like this (implemented your method in the class LocationCopy, because no class was shown in your question):
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class LocationCopy {
private int x, y, z;
//private String world;
public LocationCopy(int x/*, int y*/, int z/*, String world*/) {
this.x = x;
//this.y = y;
this.z = z;
//this.world = world;
}
public LocationCopy(Location spawner) {
this.x = spawner.getBlockX();
this.y = spawner.getBlockY();
this.z = spawner.getBlockZ();
//this.world = spawner.getWorld().getName();
}
//EDIT added toString method (just for better printing and debugging)
#Override
public String toString() {
return "LocationCopy [x=" + x + ", y=" + y + ", z=" + z + "]";
}
//EDIT: added hashCode method that is needed for the HashSets to identify objects that represent the same location
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
result = prime * result + z;
return result;
}
//EDIT: added equals method (not really needed, but better to have one...)
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LocationCopy other = (LocationCopy) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
if (z != other.z)
return false;
return true;
}
public int getX() {
return x;
}
public int getZ() {
return z;
}
public Location getLoc() {
return new Location(x, y, z);
}
public static void main(String[] args) {
List<LocationCopy> locs = createLocs();
HashMap<Location, HashSet<Location>> map = new HashMap<Location, HashSet<Location>>();
for (LocationCopy loc : locs) {
HashSet<LocationCopy> locsCopy = new HashSet<LocationCopy>(locs);
locsCopy.remove(loc);
for (LocationCopy loc2 : locsCopy) {
if (distance(loc2.getX(), loc.getX(), loc2.getZ(), loc.getZ()) <= 16) {
if (!map.containsKey(loc.getLoc())) {
HashSet<Location> hs = new HashSet<Location>();
hs.add(loc2.getLoc());
map.put(loc.getLoc(), hs);//EDIT: changed loc2 to loc
}
else {
HashSet<Location> hs = map.get(loc.getLoc());
hs.add(loc2.getLoc());
map.put(loc.getLoc(), hs);//EDIT: changed loc2 to loc
}
}
}
}
//EDIT: selecting groups for finding the center
Set<Set<Location>> groups = new HashSet<Set<Location>>();
for (Location loc : map.keySet()) {
if (map.get(loc).size() > 5) {
//EDIT: don't know what write does -> using System.out.println instead
//write("More than " + map.get(loc).size() + locToString(loc) + ": " + getLocs(map.get(loc)) + "<br>", fileName, beta);
System.out.println("More than " + map.get(loc).size() + " " + locToString(loc) + ": " + /*getLocs(map.get(loc)) + */"<br>");
//EDIT: create groups to find the center points
Set<Location> group = new HashSet<Location>();
group.addAll(map.get(loc));
group.add(loc);
groups.add(group);
}
}
//EDIT: find the center of the group
for (Set<Location> group : groups) {
Location center = findCenter(group);
System.out.println("center found: " + center);
}
}
/**
* Find the center of each group by calculating the summed distance from each point to every other point.
*
* The point that has the minimum summed distance to every other point is the center.
*/
private static Location findCenter(Set<Location> group) {
if (group.isEmpty()) {
throw new IllegalArgumentException("The group mussn't be empty");
}
List<LocationDistance> summedDistances = new ArrayList<LocationDistance>(group.size());
for (Location loc : group) {
LocationDistance dist = new LocationDistance(loc, 0);
//sum up the distance to each location in the group
for (Location loc2 : group) {
double distance = distance(loc.getBlockX(), loc2.getBlockX(), loc.getBlockZ(), loc2.getBlockZ());
dist.setDistance(dist.getDistance() + distance);
}
summedDistances.add(dist);
}
//sort the list (LocationDistance implements Comparable to do this)
Collections.sort(summedDistances);
//the first item in the list is the center
return summedDistances.get(0).getLocation();
}
private static List<LocationCopy> createLocs() {
List<LocationCopy> locs = new ArrayList<LocationCopy>();
//trying to create the example from the image in your question
locs.add(new LocationCopy(0, 0));
locs.add(new LocationCopy(2, 0));
locs.add(new LocationCopy(5, 0));
locs.add(new LocationCopy(1, 2));
locs.add(new LocationCopy(2, 1));//center
locs.add(new LocationCopy(4, 1));
locs.add(new LocationCopy(3, 2));//adding a new point because otherwhise it will never be enough for a group greater than 5
locs.add(new LocationCopy(10, 30));
locs.add(new LocationCopy(12, 31));
locs.add(new LocationCopy(15, 31));
locs.add(new LocationCopy(8, 36));
locs.add(new LocationCopy(13, 33));//center
locs.add(new LocationCopy(18, 34));
locs.add(new LocationCopy(15, 36));//adding a new point because otherwhise it will never be enough for a group greater than 5
return locs;
}
private static String locToString(Location loc) {
return loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ();
}
private static double distance(double x1, double x2, double z1, double z2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(z2 - z1, 2));
}
}
The class Location (the important part is the hashCode method):
public class Location {
public int x, y, z;
public Location(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getBlockX() {
return x;
}
public int getBlockY() {
return y;
}
public int getBlockZ() {
return z;
}
#Override
public String toString() {
return "Location [x=" + x + ", y=" + y + ", z=" + z + "]";
}
//EDIT here the hashCode is also important for the HashSets you use in your code
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
result = prime * result + z;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Location other = (Location) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
if (z != other.z)
return false;
return true;
}
}
and a new class LocationDistance for comparing distances:
/**
* A class for comparing the distances for locations
*/
public class LocationDistance implements Comparable<LocationDistance> {
private Location location;
private double distance;
public LocationDistance(Location location, double distance) {
this.location = location;
this.distance = distance;
}
#Override
public String toString() {
return "LocationDistance [location=" + location + ", distance=" + distance + "]";
}
#Override
public int compareTo(LocationDistance other) {
return Double.compare(distance, other.getDistance());
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public double getDistance() {
return distance;
}
public void setDistance(double distance) {
this.distance = distance;
}
}
The output is:
More than 6 2 0 0: <br>
More than 6 1 0 2: <br>
More than 6 2 0 1: <br>
More than 6 5 0 0: <br>
More than 6 4 0 1: <br>
More than 6 3 0 2: <br>
More than 6 10 0 30: <br>
More than 6 12 0 31: <br>
More than 6 8 0 36: <br>
More than 6 15 0 31: <br>
More than 6 13 0 33: <br>
More than 6 15 0 36: <br>
More than 6 18 0 34: <br>
More than 6 0 0 0: <br>
center found: Location [x=2, y=0, z=1]
center found: Location [x=13, y=0, z=33]
Here the last two lines are the centers you were searching for.
The issue I am having is figuring out how to link my button class to my main program. I realize I have a lot of methods from external classes so I will try to give an overview. Basically I have an arrayList of quotes and a key created from a random permutation of the alphabet. I use this key to "encrypt" the quote. Via this method:
public static String translate ( String text, String key )
{
String newText = "";
for( int i = 0; i < text.length(); i++ )
{
char currentLetter = text.charAt( i );
if( ALPHA.contains( Character.toString( currentLetter ) ) )
{
int index = ALPHA.indexOf( currentLetter );
char newLetter = key.charAt( index );
newText = newText + text.substring( i, i + 1 ).replace
( currentLetter, newLetter ) ;
}
else
newText = newText + currentLetter;
}
return newText;
}
So what I want to do is to have a button that takes user input and replaces the letters in the quote with that input. I'm not using JButton, I'm using a library to make a square and then using mouseEvent. I made the button in a separate class here:
import wheelsunh.users.*;
import java.awt.Color;
import java.awt.event.MouseEvent;
import javax.swing.JOptionPane;
/**
* Creates a button
*
* #author Scott
*/
public class SubstituteButton extends RoundedRectangle
{
String response;
public SubstituteButton( int x, int y )
{
super( x, y );
super.setSize( 20, 20 );
super.setFillColor( Color.LIGHT_GRAY );
super.setFrameColor( Color.BLACK );
}
public void mousePressed( MouseEvent e )
{
super.setFillColor( new Color( 131,111,255 ) );
try
{
response = JOptionPane.showInputDialog( "Which letter"
+ " would you like to replace? Ex. ab would replace all a's"
+ " with b's" );
}
catch( NullPointerException exeception )
{
JOptionPane.showMessageDialog( null, "Input Error" );
}
super.setFillColor( Color.LIGHT_GRAY );
}
public String getInput()
{
if( response.length() == 2 &&
Character.isLetter( response.charAt( 0 ) ) &&
Character.isLetter( response.charAt( 1 ) ))
{
return response;
}
return null;
}
public static void main( String args[] )
{
new Frame();
new SubstituteButton( 100, 100 );
}
}
HSo how would I update the displayed quote so that it replaces the letters? I was thinking I could just use the replace() method in the button class, but it doesn't update the displayed quote. Here is the main program:
import wheelsunh.users.*;
import java.util.*;
import java.lang.Character;
/**
* Displays a quote with letters in blocks and punctuation without blocks.
* If a letter has been changed from the original then it is highlighted.
* Displayed lines must be broken to stay on frame.
*
*
* #author Scott
*/
public class CryptogramApp extends ShapeGroup
{
private ArrayList< String > blockQuote;
private int quoteLength;
private SubstituteButton substituebutton;
private boolean newState = true;
private String key, quote, encryptedQuote;
/**
* Creates a block-quote with first letter at initialX,initialY
* with the text from quote.
*
* #param initialX int
* #param initialY int
* #param quote String
*/
//--------------------------------------------------------------------------
public CryptogramApp( int initialX, int initialY )
{
if( newState == true )
newQuote();
int newx = initialX;
for( int i = 0; i < quote.length(); i++ )
{
String letter = Character.toString( encryptedQuote.charAt( i ) );
BlockLetter b = new BlockLetter( newx, initialY, letter );
newx += BlockLetter.WIDTH;
if( letter.equals(" ") && b.getXLocation() > 400 )
{
newx = initialX;
initialY += 40;
}
}
newState = false;
}
public void newQuote()
{
blockQuote = new ArrayList<String>();
key = StringUtilities.getRandomKey();
quote = getRandomQuote();
System.out.println( key );
encryptedQuote = StringUtilities.translate( quote, key );
System.out.println( encryptedQuote );
substituebutton = new SubstituteButton( 425, 350 );
}
//--------------------------------------------------------------------------
/**
* Returns the String text with the jth character replaced with key.
*
* #param text String
* #param key String
* #param j int
*
* #return String
*/
public String getRandomQuote()
{
Random gen = new Random();
ArrayList< String > list = StringUtilities.getQuotes();
String quote = list.get( gen.nextInt( 6 ) );
return quote;
}
//--------------------------------------------------------------------------
/**
* Runs a simple test of CryptogramApp.
*
* #param args String[]
*/
public static void main( String args[] )
{
new Frame( 700, 500 );
new CryptogramApp( 20, 50 );
}
}
#MadProgrammer is clearly correct. Why haven't you subclassed JButton??
Now to your code,
It's not clear what error you're receiving, or what is not working for you.
Should you have
public class SubstituteButton extends RoundedRectangle implements MouseListener
and at some stage
SubstituteButton button=new SubstituteButton();
button.addMouseListener(button)
? This would connect your button to the listener.
Also, where are you adding the button to the frame?
Please post the complete code.
I read in a book that when you change the value of a method parameter that's a boolean or other basic datatype within the method it only is changed within the method and remains the same outside. I want to know if there is some way for me to actually change it within the method. For example:
public class Change {
void convert(boolean x, boolean y, boolean z) { //i want to set x,y, and z to false in this
x = false;
y = false;
z = false;
}
}
//Now in my main class:
public static void main(String[] args) {
boolean part1 = true;
boolean part2 = true;
boolean part3 = true;
System.out.println(part1 + " " + part2 + " " + part3);
Change myChange = new Change();
myChange.convert(part1,part2,part3);
System.out.println(part1 + " " + part2 + " " + part3);
}
EDIT1: These answers were good but not quite what i want to acheive. I want to put in part1, part2, and part3 when i call the method than i want them to be set to false within the method. The specific reason i asked this question was because im trying to code a battleship and i have a subroutine class with a method that when its called it checks if a ship has been sunk. If the there was a sink than the method will set a ton of boolean variables to false.
EDIT2: Just to clarify, I want something like this:
void convert(thing1,thing2,thing3,thing4) {
//some code here that sets thing1,thing2,thing3, and thing4 to false
}
// than in main:
boolean test1 = true;
boolean test2 = true;
boolean test3 = true;
boolean test4 = true;
convert(test1,test2,test3,test4);
System.out.println(test1 + " " + test2 + "....");
//and that should print out false, false, false, false
You can do it with this methodology
// these are called instance variables
private boolean x = false;
private boolean y = false;
private boolean z = false;
// this is a setter
public static void changeBool(boolean x, boolean y, boolean z) {
this.x = x;
this.y = y;
this.z = z;
}
Call the method like this
changeBool(true, true, false);
The values for x, y, and z are now changed.
This is a common problem in Java - pass-by-value vs. pass-by-reference. Java is always pass-by-value, where you're thinking of it as pass-by-reference.
Like #Rafael has said, you need to use instance variables to do what you want. I've gone a bit further and edited your source code to do what you want:
public class Change {
boolean part1;
boolean part2;
boolean part3;
Change(boolean x, boolean y, boolean z) {
part1 = x;
part2 = y;
part3 = z;
}
void convert(boolean x, boolean y, boolean z) { //this now sets the class variables to whatever you pass into the method
part1 = x;
part2 = y;
part3 = z;
}
// Now in my main class:
public static void main(String[] args) {
Change myChange = new Change(true, true, true);
System.out.println(myChange.part1 + " " + myChange.part2 + " "
+ myChange.part3);
myChange.convert(false, false, false);
System.out.println(myChange.part1 + " " + myChange.part2 + " "
+ myChange.part3);
}
}
I have some code snippet that goes like below
:
Graphics g; // Java Graphics class
g.drawString("text", x, y); // x, y for coordinate info, "text" is now an image object
:
Can I get "text" back into a String from the Graphics instance?
Since I want to use the String data as a key for getting some data from a table.
The best approach is probably to store the text in a String variable, and get it from there instead.
No, the Graphics instance just draws the text on the screen or an image as pixels. It does not remember what the text is that you drew, so it can't tell you.
You'll have to store the text some other way in your program, so that you can get it back later for whatever purpose you need it for (such as getting data from a table).
I solved this problem by adding two tables that each memorize the X and Y coordinate for the node instance being generated at the presentation layer and at model layer.
At runtime, node images continue to change its position and these events are all updated.
When I click on a node image on Panel instance, it gives the id of the node instance.
The reason why two tables are required is that only when the id returned by calling the X, Y position of the node image refers to the same node object is the evidence that the event is for the node object represented by the clicked node image. Now I realize I could have used multi-key table.
import java.util.ArrayList;
import java.util.List;
// * Represents node at presentation layer and its model
public class NodeObject
{
// * node id
private int id;
// * coordinate on Panel
public double x;
public double y;
// * coordinate change
private double dx;
private double dy;
// * isFixed
public boolean fixed;
// * node name
public String nodeName;
// * connected node object id list ( redundant when edge is used )
public List<Integer> connectedNodeIdList;
// * connected edge object id list
private List<Integer> connectedEdgeIdList;
// * constructor
public NodeObject()
{}
// * constructor
public NodeObject( int _id )
{
// * initialization
this.id = _id;
// * default
this.nodeName = "default";
// * connected node id list
this.connectedNodeIdList = new ArrayList<Integer>();
}
// * Constructor ( when node name is given )
public NodeObject( int _id, String _nodeName )
{
// * node id
this.id = _id;
// * node name
this.nodeName = _nodeName;
// * connected node id list
this.connectedNodeIdList = new ArrayList<Integer>();
// * connected edge id list
this.connectedEdgeIdList = new ArrayList<Integer>();
}
// * set node name
public void setNodeName( String nName )
{
this.nodeName = nName;
}
// * get node id
public int getNodeId()
{
return this.id;
}
// * get node name
public String getNodeName()
{
return this.nodeName;
}
// * get node name and id in String
public String getNodeNameWithID()
{
String id = Integer.toString( this.getNodeId() );
return ( this.nodeName + "-" +id );
}
// * store connected node
public boolean addSingleNode( int nid )
{
if ( this.connectedNodeIdList.contains( nid ) == true )
{
return true; // this node is already connected
}
else
{
// * register
this.connectedNodeIdList.add( nid );
// * this is the first time this node is connected
return false;
}
}
// * unregister a node
public boolean removeConnectedSingleNode( int nid )
{
// * it was registered before
if ( this.connectedNodeIdList.contains( nid ) == true )
{
this.connectedNodeIdList.remove( nid );
return true; // it had been registered and now unregistered ( only at model layer )
}
else
{
return false; // it has not been registered before.
}
}
// * add edge id
public boolean addSingleEdge( int eid )
{
if ( this.connectedEdgeIdList.contains( eid ) == true )
{
return true; // already registered edge
}
else
{
// * registered
this.connectedEdgeIdList.add( eid );
// * this is the first time this edge was connected
return false;
}
}
// * remove edge
public boolean removeConnectedSingleEdge( int eid )
{
// * registered before
if ( this.connectedEdgeIdList.contains( eid ) == true )
{
this.connectedEdgeIdList.remove( eid );
return true; // now removed ( model level )
}
else
{
return false; // it has not been registered before
}
}
// * return edge id list
public List<Integer> getEdgeIdList()
{
return this.connectedEdgeIdList;
}
//////// for visualization on Panel instance ///////
// * X coordinate setting
public void setNodePositionX( Double xPos )
{
this.x = xPos;
}
// * Y coordinate setting
public void setNodePositionY( Double yPos )
{
this.y = yPos;
}
// * change of node position
public void changeNodePosition( Double changeX, Double changeY )
{
this.x = this.x + changeX;
this.y = this.y + changeY;
}
// * position difference
public void changeNodePositionDifference( Double changeDX, Double changeDY )
{
this.dx = this.dx + changeDX;
this.dy = this.dy + changeDY;
}
// * update node position difference
public void updateNodePositionDifference( Double changeDX, Double changeDY )
{
this.dx = changeDX;
this.dy = changeDY;
}
// * get X pos
public double getNodePositionX()
{
return this.x;
}
// * get Y pos
public double getNodePositionY()
{
return this.y;
}
// * get dx
public double getNodePositionDX()
{
return this.dx;
}
// * get dy
public double getNodePositionDY()
{
return this.dy;
}
}
And the Graph class goes like below
public class Graph extends Panel implements Runnable, MouseListener, MouseMotionListener, ItemListener
{
// * number of nodes
public int nnodes;
// * node generator
public NodeGenerator ndGenerator;
// * memorize the node coordinate
public Map<Integer, Integer> xCoordinateTbl; // key : coordinate / value : node id
public Map<Integer, Integer> yCoordinateTbl;
// * node tbl
public Map<Integer, NodeObject> nodeTbl;
Once mouse click event occurs, it is handled like below
public void actionPerformed(ActionEvent event)
{
// * get node id of the node object being referred to at the presentation layer
Integer nid = getNodeId( e.getPoint().x, e.getPoint().y );
// * remove node on the presentation layer and of the model at the same time
removeSingleNode( nid );
}