Unexpected endless loop appears - java

I've got an ArrayList filled with 500 Point-Objects. There might be duplicates in it so I want to find them and if needed delete them except for one. The plan is: Check for each Point in the arrayList, if there is an equal Point, if so, add it to a List, after the test for each Point, delete all Points from the original List that are also in the toRemove-List.
But here comes the Problem: If i run this, its going for an endless loop. Do I have a serious thinking error? I think it might be a really simple misstake but I cant think about it
Also, if you have any proposal on how to do this better, let me know.
This is my method:
private void checkForDuplicates() {
ArrayList <Point> toRemove=new ArrayList<Point>();
int i=0;
while(i<points.size()) {
Point local=points.get(i);
for (Point p: points) {
if (local!=p && local.equals(p)) {
toRemove.add(p);
}
}
for (Point p: toRemove) {
points.remove(p);
}
i++;
}
}
Update:
Something is really broken. It looks like the method might work right now, but my programm isnt. The code isnt running anymore if I call this method somewhere. I cant even print out something on the console as the first line in my main method while i call checkForDuplicates() somewhere else?!
Point:
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public boolean equals(Object p) {
if (this == p) {
return true;
}
if (!(p instanceof Point)) {
return false;
}
Point point = (Point) p;
return this.getX() == point.getX() && this.getY() == point.getY();
}
}

I recommend using streams for this task:
List result =
points
.stream()
.distinct()
.collect(Collectors.toCollection(ArrayList::new));
To make distinct() work as expected, you will probably have to define an equals()method for your Point class.

User Frank Puffer has answered the question in Java 8. It seems as if you're in older version of Java, so the following might help you. It just creates a Set object and copies the ArrayList to it. Because the Set will remove the duplicates automatically you don't need to make the code much more complexer than it should be, and is less error prone.
private void removeDuplicates() {
Set<Point> distinctPoints = new HashSet<>();
for (Point p : points) {
distinctPoints.add(p);
}
points = new ArrayList<String>(distinctPoints);
}
And include the following method impl to the Point class so that Point objects can be searched in the Set:
#Override
public int hashCode() {
int hashValue = 11;
hashValue = 31 * hashValue + x;
hashValue = 31 * hashValue + y;
return hashValue;
}
#Override
public String toString() {
return "Point[" + X + ", " + Y + "]";
}
The toString() method is a nice to have feature.

Related

how to check if parameters of 2 instances (one unknown) are the same

I have already checked similar questions, but none really answered mine.
I may have multiple instances of Tile and i must check with each new construction if there is already an object Tile with the same Coordinate2D.
Coordinate2D is made up of (int x, int y).
My questions is, while i create a Tile with a the known Coordinate2D, how do i find out if there already is a Tile with the same object Coordinate2D as a parameter so i can throw a TileExistsException?
public Tile(Coordinate2D coord, int value)throws TileExistsException {
this.coord = coord;
this.value = value;
}
Keep a set of all parameter values used so far and check it in your constructor. It must be static so all instances share the same data.
private static Set<Coordinate2D> coordinates = new HashSet<>();
public Tile(Coordinate2D coord, int value) throws TileExistsException {
if (!coordinates.add(coord)) {
throw new TileExistsException();
}
this.coord = coord;
this.value = value;
}
The add() method of Set returns true if the set was changed by the operation, so it will return false if the coordinate has already been used.
Note
For HashSet to work, your Coordinate2D class must implement hashCode() and equals() based on the fields that identify the instance, which I imagine would be x and y, eg something like:
public class Coordinate2D {
int x;
int y;
public boolean equals(Object o) {
return o instanceof Coordinate2D && ((Coordinate2D)o).x == x &&((Coordinate2D)o).y == y;
}
public int hashCode() {
return Objects.hash(x, y);
}
// other methods and fields
}

Inheritance getter and toString() - java

I'm practicing inheritance in Java and got stuck on getter method in subclass.
Here is the Point class:
package OOP.LinePoint;
public class Point {
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
public String toString() {
return "Point: (" + x + "," + y + ")";
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Here LineSub class:
package OOP.LinePoint;
public class LineSub extends Point{
Point end;
public LineSub(int beginX, int beginY, int endX, int endY){
super(beginX, beginY);
this.end = new Point(endX, endY);
}
public LineSub(Point begin, Point end){
super(begin.getX(),begin.getY());
this.end = end;
}
#Override
public String toString() {
return "LineSub [begin=" + "(" + super.getX() +"," + super.getY() +") " + "end=" + end + "]";
}
public Point getEnd() {
return end;
}
public void setEnd(Point end) {
this.end = end;
}
public Point getBegin(){
}
public void setBegin(Point begin){
setX(begin.getX());
setY(begin.getY());
}
}
My problem:
1) toString() method. I'm trying to print two points(begin and end). As you can see end is easy but begin Point is inherited and idk what should I type. The way I'm getting x and y of point is working but for me it seems to be lame way of doing that. For sure there is a better way, could you please help me with that?
2) Point getBegin() method. I've tried:
public Point getBegin(){
return (Point)this;
}//Not working(getting whole Point object)
and
public Point getBegin(){
return new Point(getX(), getY());
}//Very noob way
I have no other ideas, please lend me your wisdom.
IMHO, it is not a good use of inheritance. Your case is not a valid candidate for Inheritance.
A class is a good candidate for inheritance only when it conforms to is-A relationship.
A Line is not a Point but it a collection of points (In your case it is being and end).
So, It is a good candidate for composition (Has-A).
A line HAS a begin and an end point. You are using both inheritance (For begin point) and composition (For end point) for code reuse.
Adhere to composition and have two points (begin and end) in Line class.
To get the start Point you must cast yourself to a Point. You can call your super.toString to access the toString of the parent class.
#Override
public String toString() {
return "LineSub [begin=" + super.toString() + "end=" + end.toString() + "]";
}
public Point getBegin() {
return (Point) this;
}
The fact that you have to cast is an indicator that you have your hierarchy wrong. This structure would normal be implemented using two points.
public class LineSub {
Point begin;
Point end;

Java ArrayList new elements not creating

I'm trying to create ArrayList with elements from Database. I can get data from DB without any problem, but my problem occurs when I'm trying to create ArrayList of objects. It just doesn't exist. I've declared my list in my main class like this:
private static ArrayList<Vertex> vertexList = new ArrayList<Vertex>();
In my getData() function shown below
private static void getData() throws SQLException{
result = query.executeQuery("SELECT * FROM GTABLE ORDER BY X,Y");
while (result.next()){
int x = result.getInt("X");
int y = result.getInt("Y");
float p = result.getFloat("P");
System.out.printf("X:%d\tY:%d\tP:%.3f\n",x,y,p);
addData(x,y,p);
addData(y,x,p);
}
}
I'm getting all the data from database. Everything works fine until I get to my function addData(x,y,p) shown below:
private static void addData(int x, int y, float p){
Edge edge;
int tmp;
Vertex vertex = new Vertex(x);
edge = new Edge(x,y,p);
//vertex.edgeList.add(edge);
tmp = ifVertexExists(vertex);
if(tmp < 0){
vertexList.add(vertex);
} else {
//vertexList.get(tmp).edgeList.add(edge);
}
}
It just doesn't create anything in my list. I've checked it with isEmpty() and it it was empty.
Any help will be appreciated.
EDIT Here's my Vertex class:
class Vertex{
private final int vertID;
public Vertex(int x){
this.vertID = x;
}
public int getVertID(){
return vertID;
}}
ifVertexExists
private static int ifVertexExists(Vertex vL){
for(Vertex v : vertexList){
if(v.getVertID() == vL.getVertID()){
System.out.printf("Vertex is on the list\n");
return -1;
} else {
System.out.println("No vertex with this ID\n");
}
}
return 0;
}
Right now, I can create the list and it works well, the vertex are shown on screen, tmp is -1. It was bad ifVertexExists, thanks to everyone who helped.
Presumably the response from ifVertexExists is always > 0. Use a debugger or insert print statements to verify this.
I think your vertex class needs to implement equals to be used with ArrayList.contains which you might be using in ifVertexExists.

Trying to print out the contents of an ArrayList

I'm trying to print out the contents of the ArrayList "list", but I keep getting what I think is the locations of the elements and not the contents.
import java.util.*;
public class Assignment23 {
public static void main (String[] args){
ArrayList<Point> list = new ArrayList<Point>();
for(int i = 0; i < 99; i++){
list.add(new Point());
}
Collections.sort(list);
System.out.println(""+list);
}
}
class Point implements Comparable<Point>{
int x = (int)(Math.random()*-10);
int y = (int)(Math.random()*-10);
To print out the contents of the ArrayList, use a for loop:
for (Point p : list)
System.out.println("point x: " + p.x ", point y: " + p.y);
You will find you get much better results for this and in many situations if you implement toString for Point and most classes that you write. Consider this:
#Override public String toString()
{
return String.format("(%d,%d)", x, y);
}
Over write toString method in point
class Point implements Comparable<Point>{
int x = (int)(Math.random()*-10);
int y = (int)(Math.random()*-10);
#Override
public String toString()
{
return "["+x+","+y+"]";
}
}
Usage is same :
Collections.sort(list);
System.out.println("Points["+list+"]);
You will get output like
Points[[20,10],[15,10]...]
Override toString() method on Point class.
class Point implements Comparable<Point>{
#Override
public String toString() {
return "x =" + x + ", y="+y;
}
}
Change it to:
System.out.println(""+list.get(i).x); //Or whatever element in `Point` you want to print
The reason you were getting an unexpected result is that your list consists of Point objects. So calling list.get(i) returns an entire Point, whereas you want to specify that field in the Point to print out.

Sort a list that contains a custom class

so I'm currently doing an exercise for college that has several optional parts (because we havn't done this in class yet), one of them being to use lists instead of arrays (so it'd be variable size) and another one printing the list sorted by points (I'll get to that now)
So, I have the Player.java class which looks like this.
public class Player {
String name;
String password;
int chips;
int points;
public Player(String n, String pw, int c, int p) {
name = n;
password = pw;
chips = c;
points = p;
}
public String getName() {
return name;
}
public void setName(String n) {
name = n;
}
public void setPW(String pw) {
password = pw;
}
public String getPW() {
return password;
}
public void setChips(int c) {
chips = c;
}
public int getChips() {
return chips;
}
public void setPoints(int p) {
points = p;
}
public int getPoints() {
return points;
}
}
Pretty simple, then I'm creating a List with this (in another class):
List<Player> lplayer = new ArrayList<Player>();
Adding players with this:
lplayer.add(new Player(n,pw,c,p))`
And finally reading their stats with this:
public int search_Player (String n) {
String name;
int i = 0;
boolean found = false;
while ((i <= tp) && (!found)) {
name = lplayer.get(i).getName();
if (name.equals(n)) {
found = true;
}
i++;
}
return (found == true) ? i-1 : -1;
}
public Player show_Player (int i) {
return lplayer.get(i);
}
public void list_Players() {
Collections.sort(lplayer);
int i2;
if (tp > 0) { // variable which contains number of total players
for (int i = 0;i<tp;i++) {
i2 = i+1;
System.out.println ("\n"+i2+". "+lplayer.get(i).getName()+" [CHIPS: "+lplayer.get(i).getChips()+" - POINTS: "+lplayer.get(i).getPoints()+"]");
}
}
else {
System.out.println ("There are no players yet.");
}
}
So that's basically all the code. As you can see the I already have a list_Players function but that just prints it in the order it was added. I need a way to print in sorted by the points each player has (so basically a ranking).
As you can see I'm pretty new to java so please try not to come up with a very complicated way of doing it.
I've already searched for it and found things like Collections.sort(list) but I guess that's not what I need right here.
Thank you!
You can use the public static <T> void sort(List<T> list, Comparator<? super T> c) overload in Collections - provide the comparator you need (can be just an anonymous class) - and you are all set!
EDIT:
This describes how the method works. In brief, you'll implement your call as
Collections.sort(list, new Comparator<Player>() {
int compare(Player left, Player right) {
return left.getPoints() - right.getPoints(); // The order depends on the direction of sorting.
}
});
That's it!
Collections.sort(list) could definitely by a solution for your problem. It's a way to sort your collections provided by Java. If you are writing a "real world" application (not an exercise for collage) this would be the way you doing it.
To let Collections.sort(list) works, you have to implement an interface call Comparaple. By implementing this interface, the sort will know how to order your elements.
But because it's a exercise for collage, this is perhaps a little bit to easy. If you want (or must) implement you own sorting algorithm, try first to sort a common list of numbers (1, 5, 2, 7...). You can extend such an sorting algorithm easily for your own classes.
A new approach using lambdas, that is a lot shorter to write is
myList.sort((obj1, obj2)->(condition)?1:-1);
where you can use the objects for your condition, and anything greater than 0 returned means swap (in this case if condition returns true)

Categories

Resources