Comparing classes that contains two numbers - java

So, I have a class that contains two numbers, more exactly X and Z. I'm storing it on a TreeMap, that needs the key class implement Comparable. The problem is, how am I going to compare the X and Z to other class on the compareTo() method?
I have already tried to add up the X and Z integers for the both classes and comparing them with Integer.compare(), but this is not a good solution because if X and Z are switched, it will end on the same result.
public class Position2D implements Comparable<Position2D> {
private int x, z;
#Override
public int compareTo(Position2D position2D) {
int coordinatesSum = this.getX() + this.getZ();
int otherCoordinatesSum = position2D.getX() + position2D.getZ();
return Integer.compare(coordinatesSum, otherCoordinatesSum);
}
}

Solved with:
#Override
public int compareTo(#Nonnull Position2D position2D) {
int xComparison = Integer.compare(this.getX(), position2D.getX());
int zComparison = Integer.compare(this.getZ(), position2D.getZ());
return xComparison != 0 ? xComparison : zComparison;
}
Special thanks to #harold.

Related

Parameters and arguments from one class to another in java

I'm half way through an assignment in java where I have two classes and need to calculate a x- and y-position. I get half of the tests correct but can't seem to get the two last ones correct. Could you perhaps guide my in the right direction?
I have one class calle Point and one PointMain. I get the arguments in PointMain and need to create the right methods in Point. I can't make any changes in the class PointMain as I got that from the assignment.
Class Point:
public class Point {
private int x = 0;
private int y = 0;
public Point() {
}
public Point(int xPoint, int yPoint) {
x = xPoint;
y = yPoint;
}
public String toString() {
return x + "," + y;
}
public double distanceTo(Point p2) {
double avstand = Math.sqrt(((p2.x*1 - p2.x*2) * (p2.x*1 - p2.x*2)) + ((p2.y*1 - p2.y*2) * (p2.y*1 - p2.y*2)));
return avstand;
}
public void move(int iPoint, int jPoint) {
x = x + iPoint; // I have a problem with this that it doesn't add
y = y + jPoint; // the 3,4 that I got from p2 with the 5,-2.
}
public void moveToXY(int xTag, int yTag) {
}
public boolean isEqualTo(Point p2) { //And I'm not really sure on how to
return false; //construct this method either...
}
}
Class PointMain:
public class PointMain {
public static void main(String[] args) {
Point p1 = new Point();
Point p2 = new Point(3,4);
System.out.println(p1.toString()); // ==> (0,0)
System.out.println(p2.toString()); // ==> (3,4)
if (p1.isEqualTo(p2)) // False!
System.out.println("The two points are equal");
double dist = p1.distanceTo(p2);
System.out.println("Point Distance: "+dist);
p2.move(5,-2); // ==> (8,2)
p1.moveToXY(8,2); // ==> (8,2)
System.out.println(p1);
System.out.println(p2);
if (p1.isEqualTo(p2)) // True!
System.out.println("The two points are equal");
}
}
First of all you should add getters
public int getX()
{
return x;
}
public int getY()
{
return y;
}
Than implement isEqual
public boolean isEqualTo(Point p2) {
return x == p2.getX() && y == p2.getY();
}
you can also declare x and y public and then there is no need for getters and code is simpler as you can see in implementation of java.awt.Point.
I don't see problem with "move" function.
And last
public void moveToXY(int xTag, int yTag) {
x = xTag;
y = yTag;
}
For additional info you can lookup how java.awt.Point implemented, and work on your function parameters naming iPoint/jPoint is horrible names
For the equality method, think that in which condition the two points are equal. Consider using if for validating the condition and getters for getting the points x and y.
And I don't see any problem with the move method.
And as #Juniar said in the comments, there's another problem in your distanceTo method. You want to get x and y of p2 but they are private variables so you can't have them by this way. In this case your are having the x and y of the object which the method is called on. So the output won't be desirable. (see getters again)

Java generics - accept float and int

How can I program my class to accept both Integers and Floats, I suppose I'll need to use generics, am I correct?
public class Vec2 {
private int x, y;
public Vec2(int xa, int ya) {
this.x = xa;
this.y = ya;
}
public Vec2() {
this(0, 0);
}
public Vec2(Vec2 vec) {
this(vec.x, vec.y);
}
public void addX(int xa) {
x+=xa; // I get an exception here when I try to use generics.
}
public void addY(int ya) {
y+=ya; // I get an exception here when I try to use generics.
}
Any ideas how to program my class to accept floats, integers and doubles altogether?
For the time being, we cannot have generics over primitives like int or double, so you will be forced to use boxed representations. It really is easier to just make a separate class for int and double. But if you want to use generics, here's how you can do it in a type-safe way (using java8):
public class Vec2<T> {
private final BinaryOperator<T> adder;
private T x, y;
private Vec2(BinaryOperator<T> adder, T x, T y) {
this.adder = adder;
this.x = x;
this.y = y;
}
public void addX(T xa) {
x = adder.apply(x, xa);
}
public void addY(T ya) {
y = adder.apply(y, ya);
}
public static Vec2<Integer> ofInt(Integer x, Integer y) {
return new Vec2<>(Integer::sum, x, y);
}
public static Vec2<Double> ofDouble(Double x, Double y) {
return new Vec2<>(Double::sum, x, y);
}
}
Vec2<Integer> intvec = Vec2.ofInt(5, 3);
intvec.addX(8);
Vec2<Double> dblvec = Vec2.ofDouble(5.2, 8.9);
dblvec.addY(-.9);
You could use BigDecimal to back your Vec2 and then you could use create addX and addY method(s) for long and double fairly easily. Something like,
public class Vec2 {
private BigDecimal x, y;
public Vec2(double xa, double ya) {
this.x = BigDecimal.valueOf(xa);
this.y = BigDecimal.valueOf(ya);
}
public Vec2(long xa, long ya) {
this.x = BigDecimal.valueOf(xa);
this.y = BigDecimal.valueOf(ya);
}
public Vec2(Vec2 vec) {
this.x = vec.x;
this.y = vec.y;
}
public void addX(double xa) {
x = x.add(BigDecimal.valueOf(xa));
}
public void addX(long xa) {
x = x.add(BigDecimal.valueOf(xa));
}
public void addY(double ya) {
y = y.add(BigDecimal.valueOf(ya));
}
public void addY(long ya) {
y = y.add(BigDecimal.valueOf(ya));
}
#Override
public String toString() {
return String.format("x = %s, y = %s", x.toString(), y.toString());
}
}
No, you don't, merely have your class inherit from Number and use type checking to ensure that values are of the appropriate class, if necessary, e.g.
Class IsraelG99sClass {
Number n;
public Number add(Number n2) {
if (n instanceof Integer && n2 instanceof Integer) {
return new Integer(n.intValue() + n2.intValue());
} else {
return new Double(n.doubleValue() + n2.doubleValue());
}
}
public Number getValue() {
if ((n instanceof Integer) || (n instanceof Float)) {
return n;
} // handle the other case as appropriate
}
}
Floats and ints are very different values with vastly different mins and maxes. I would try using doubles as the data member with overloaded constructors for different variable types instead of generics unless generics are really needed.
Yes, you can use generics and make your x and y attributes of type T.
But you won't be able to just implement the addX and addY in they way you want.
Check these other answers on how to implement a generic number addition, it's not as simple but you should be able to do it that way.
Java Generics and adding numbers together
how to write a generic method for adding numbers
First of all, I'm operating under the assumption that you want x and y to be of varying (generic) type.
For this, you would want:
public class Vec2<E extends Number> {
private E x, y;
public Vec2(E xa, E ya) {
this.x = xa;
this.y = ya;
}
//Not _easily_ possible with generics, as the compiler has no guarantee that
//zero is an acceptable value. Consider some variation of a Factory pattern,
//but this will work. Note that there is an "officially"-unchecked cast warning.
public Vec2() {
super();
final Number zero = 0.0;
this.x = (E)zero;
this.y = (E)zero;
}
public Vec2(Vec2<E> vec) {
this(vec.x, vec.y);
}
public void addX(E xa) {
Number c = x.doubleValue() + xa.doubleValue();
x = (E)c;
}
public void addY(E ya) {
Number c = y.doubleValue() + ya.doubleValue();
x = (E)c;
}
This should work well. While I encourage you to use generics, note that keeping a numeric type (like int, float, or double) as a generic is often not advisable, as they're only similar on the surface. When you dig into the operations of, say, "+", they are radically different dependent on type. You will also have an assortment of unchecked-cast warnings in this code; perhaps I could have rooted them out properly had I the time, but this just goes back to my warning about generic numbers.
You will also notice a few flukes of the language doing this, such as the way that (E)zero works, but (E)(0.0) does not.
By and large, though, generics are a much easier and cleaner way to go about things than inheritance, when it is possible.

Working with multiple arrays and incrementing objects within them

Suppose I have these classes:
public class EdgeI {
public int from;
public int to;
public EdgeI (int a1, int a2) {
from = a1;
to = a2;
}
}
public class VertexI {
public List neighbors;
public String info;
public VertexI (List neig, String str) {
neighbors = neig;
info = str;
}
}
public class vertexWeight {
public int v;
public int w;
public vertexWeight (int vertexNum, int wum) {
v = vertexNum;
w = wum;
}
}
Suppose I have a list of EdgeI objects that contain pairs of numbers. Suppose I also have a list of VertexI objects that contain an empty list and a string. I want to add the following to the empty list:
Suppose I have this as my list of EdgeI objects
(1,2), (1,2) (1,2), (1,3), (1,3), (1,4)
For the first VertexI object in the list, I want to add the following list
(2,3) (3,2)
to the vertex object. Basically I want to take the "to" integer and the number of times that "to" integer repeats and create vertexWeight objects to add to the list of neig from the VertexI class. So neig for the first VertexI object would be the vertexWeight objects (2,3) and (3,2). To implement this I created this so far:
public void createGraph () {
int oldFrom = -1;
int oldTo = -1;
for(int i = 0; i < edges.size(); i++) {
EdgeI e = edges.get(i);
int from = e.from;
int to = e.to;
VertexI v = vertices.get(from);
v.neighbors.add(new vertexWeight (to, 1));
if (from == oldFrom && to == oldTo){}
//have to add increment the number 1 in the vertex weight object somehow
else {
oldFrom = from;
oldTo = to;
}
}
}
I need some tips or methods to go about implementing this? My logic may be incorrect, thats where I need the most help I think.
I/we are having to make some assumptions about what you want to do -- for instance, in your example, the 'to' values are small, simple integers, but we have no indication that all 'to' values are in that category.
I recommend creating a HashMap entry for each 'to' value; the index is either an Integer or a Float (or a double) that corresponds to your 'to' entry, and the value holds an int that you can increment each time that 'to' value is encountered.
If that doesn't solve your problem, perhaps you can explain more of what you need.

ArrayList of my objects, indexOf problem

I have problem with Java's ArrayList. I've created an Object, that contains two attributes, x and y. Now I've loaded some object in my ArrayList. Problem is that I don't know how to find index of some object with x atribute I'm searching. Is there any way to do this?
Assuming something like:
public class Point {
public final int x;
public final int y;
}
And a declaration of:
List<Point> points = ...;
You can use for-each to iterate through all the points and find the one you want:
for (Point p : points) {
if (p.x == targetX) {
process(p);
break; // optional
}
}
Note that this will not give you the index, but it will give you the Point itself, which sometimes is enough. If you really need the index, then you'd want to use indexed for loop, using size() and get(int index) (see BalusC's answer).
See also
Java Language Guide: the for-each loop
java.util.List API
The above solution searches in O(N) for each targetX. If you're doing this often, then you can improve this by declaring class Point implementsComparable<Point>, using x as the primary sorting key for Collections.sort.
Then you can Collections.binarySearch. With a setup time of O(N log N), each query can now be answered in O(log N).
Another option is to use a SortedSet such as a TreeSet, especially if what you have is a Set<Point>, not a List<Point>.
See also
How to sort an array or ArrayList<Point> ASC first by x and then by y?
Java: What is the difference between implementing Comparable and Comparator?
Is this what you looking for?
public class Point {
private final int x;
private final 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 o) {
return (o instanceof Point && getX() == ((Point) o).getX() && getY() == ((Point) o)
.getY());
}
}
public class TestIndexOf {
public static void main(String[] args){
Point p1 = new Point(10,30);
Point p2 = new Point(20,40);
Point p3 = new Point(50,40);
Point p4 = new Point(60,40);
List<Point> list = new ArrayList<Point>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
System.out.println(list.indexOf(p3));
}
}
If you just want to search on the x property, change the equals method to compare only the x values like:
#Override
public boolean equals(Object o) {
return (o instanceof Point && getX() == ((Point) o).getX());
}
Just iterate over the list and test every element.
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getX() == someValue) { // Or use equals() if it actually returns an Object.
// Found at index i. Break or return if necessary.
}
}
Verbose, yes, but possibly until JDK7 with Closures, there is no other standard way.
I usually just use a map if i want to be able to fetch an object out of a collection based on one specific attribute value. I find that cleaner than having to iterate over lists.
Map<String, Object> map = new HashMap<String, Object>();
map.put(o1.getX(), o1);
map.put(o2.getX(), o2);
now, if i want the object that has an x-value of "foo", all it takes is
Object desiredObject = map.get("foo");
if order is important, consider a LinkedHashMap.

How to use a List of arrays in Java?

I want to declare a List<int[]> or Map<int[],Boolean> but it's very difficult because arrays in Java doesn't implement the equals() method. If two arrays a and b are equal, a.equals(b) returns false.
Although java.util.Arrays.equals() compares arrays for equality, how do I get a List to use that method for comparison instead of the screwed-up equals()?
By the way, the int[] is a array [x,y,z] describing a coordinate. I want to put a bunch of these coordinates into a List or Map.
Why not declare your own class for a point? e.g.
class Point3D {
int x, y, z;
public boolean equals() {
// logic
}
}
and then declare List<Point3D>.
A general solution is to wrap the array in a method that does implement equals (and hashCode and perhaps compare, possibly toString and other methods that might make sense) as you wish:
public final class IntArrayWrapper {
private final IntArrayWrapper[] values;
public IntArrayWrapper(int... values) {
if (values == null) {
throw new NullPointerException();
}
this.values = values;
}
#Override public boolean equals(Object obj) {
if (!(obj instanceof IntArrayWrapper)) {
return false;
}
IntArrayWrapper other = (IntArrayWrapper)obj;
return java.util.Arrays.equals(this.values, other.values);
}
#Override public int hashCode() {
return java.util.Arrays.hashCode(values);
}
public int[] getValues() {
return values;
}
[...]
}
In this specific case, using arrays to contain certain fixed data values is poor design. Do it properly:
public final class Point {
private final int x;
private final int y;
private final int z;
public static Point of(int x, int y, int z) {
return new Point(x, y, z);
}
private Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
#Override public boolean equals(Object obj) {
if (!(obj instanceof Point)) {
return false;
}
Point other = (Point)obj;
return
this.x == other.x &&
this.y == other.y &&
this.z == other.z;
}
#Override public int hashCode() {
int hash;
hash = x;
hash = hash*41+y;
hash = hash*41+z;
return hash;
}
[...]
}
First of all, this isn't legal syntax. List can only take a single generic type.
Second, I would say that if you're worried about doing things at this low a level you aren't thinking abstractly enough. An array of arrays or a List of Lists is common enough. People who create matrix classes for linear algebra use them all the time. But you leverage objects and Java best when you hide those implementation details from clients of your class. Try it for your case and see if it helps.
You could always use the existing Point3d class instead of an array.
edit: The Apache Commons Math library also has some good options.

Categories