Win a copy of Think Java: How to Think Like a Computer Scientist this week in the Java in General forum!

# HashSet problem

Vinay Naga
Greenhorn
Posts: 6
Hi,

I am trying write a program that has three sets with points defined by
Set A = {{x1, y1}, {x2, y2},{x3, y3} ...}
Set B = {{x1, y1}, {x2, y2}}
Set C = {{x2,y2},{x3,y3},{x4,y4},....}

I need to get the elements of the set such that ((A-B)intersection(C))

I have written the following program

public class sample {
HashSet<int[][]> shapeA = new HashSet<int[][]>();
HashSet<int[][]> shapeB = new HashSet<int[][]>();
HashSet<int[][]> shapeC = new HashSet<int[][]>();
int arrayA[][] = {{0,0},{100,50},{300,500}, {50, 100}, {0,0}};
int arrayB[][] = {{0,0},{100,50}};
int arrayC[][] = {{40,40},{50,100},{300,500}, {50, 100}, {40,40}};
int resultant[][] ;
Iterator<int[][]> resultantarray ;

public static void main(String args[]){
sample sam = new sample();
sam.logic();
}

public void logic(){

shapeA.removeAll(shapeB);

shapeC.retainAll(shapeA);

resultantarray = shapeC.iterator();

while (resultantarray.hasNext())
{
resultant = resultantarray.next();
}

for (int i = 0 ; i < resultant.length; i ++)
{
System.out.println(resultant[i][0]);
}
}
}

But when I inspect (am using Eclipse) the variables in this line :

shapeA.removeAll(shapeB);

The HashSet shapeA does not seem to remove the points in HashSet shapeB. I see all the variables in shapeA as it is. Please let me know what I am doing wrong here.

Vinay

Jeanne Boyarsky
author & internet detective
Marshal
Posts: 34375
345
Vinay,
HashSet uses the equals() method to determine whether two objects are the same and should be removed. And int[] has equals() implemented to check if two objects are pointing to the same int[]. It does not check that the values in the int[] are the same.

Since shapeA and shapeB have references to different physical int[]'s, they are not considered the same and are therefore not removed.

You can write your own comparator with the desired implementation and pass it to the HashSet to get the desired functionality.

Rob Spoor
Sheriff
Posts: 20527
54
Originally posted by Jeanne Boyarsky:
You can write your own comparator with the desired implementation and pass it to the HashSet to get the desired functionality.

Aren't you confusing HashSet with TreeSet? HashSet can only use the object's hashCode() and equals() methods.

What of course is also possible is create a wrapper class:

Vilmantas Baranauskas
Ranch Hand
Posts: 89
Another problem is that you add only one object to your set.

You would need to define your sets and add elements as following:

Set<int[]> shapeA = new HashSet<int[]>();
Set<int[]> shapeB = new HashSet<int[]>();
Set<int[]> shapeC = new HashSet<int[]>();

...

However this will not solve your problem because of the reason Jeanne explains.

Rob Spoor
Sheriff
Posts: 20527
54
You do know that Arrays.asList will return a List<int[]> containing only one element this way, right? You can't autobox from int[] to Integer[].

Vilmantas Baranauskas
Ranch Hand
Posts: 89
The original code puts a single array into each of sets.

My code puts a list of arrays (int[] arrays) into each of sets. There is no need to autobox from int[] to Integer[] in my code.

The best solution would probably be to define a Point class containing x and y fields as well as equals() method.

BTW, is the order of points important? If so, simple Set will not suffice. You may then create Point class with x, y and n, where n would point to Point's position in a SortedSet. Then you need to write custom Comparator to sort points by n.

Rob Spoor
Sheriff
Posts: 20527
54
I just don't see the difference between the two following:

The first adds one int[] to the HashSet<int[]>.

The second takes that same int[], puts it in a List<int[]> of size 1, then adds each element of that List<int[]> to the HashSet<int[]>. In other words, it still adds the one int[] to the HashSet<int[]>, but it takes some steps to do it.

If you would use add instead of addAll, then you would be adding a List<int[]> to the HashSet<int[]>. Which of course fails to compile due to incompatible types.

I do like your idea of using a Point class though. However, instead of creating a new class, use java.awt.Point instead. Sure, it's not Comparable, but you can use a Comparator<Point> if needed.

Vinay Naga
Greenhorn
Posts: 6
Thanks Jeanne, Rob and Vilmantas.
Yes, I need to create something like a point class. And the order of the elements in each of the points is also important. Let me post the actual problem and the solution I came up with. But it is not complete because It still fails with respect to the order. i.e. The points {10,50} and {50,10} are treated same in my code, which is wrong.

Problem :
===================
Shape A defined by a set of (x,y) points in the cartesian xy - plane.
Shape B defined by a set of (x,y) points in the cartesian xy -plane which creates a hollow hole inside of shape A.
Shape C defined by a set of (x,y) points in the cartesian xy-plane.
Write a JAVA console or windows program to find Shape E. E is the intersection of shape C with shape A where A has a hole shape B.
E is a set of (x,y) points in the cartesian xy - plane.

Input of program:
Input for A e.g. (Ax1,Ay1), (Ax2,Ay2), (Ax3,Ay3)�
Input for B e.g. (Bx1,By1), (Bx2,By2), (Bx3,By3)�
Input for C e.g. (Cx1,Cy1), (Cx2,Cy2), (Cx3,Cy3)�
Ouput of program :
Output for E e.g. (Ex1,Ey1), (Ex2,Ey2), (Ex3,Ey3)�

===================================

Solution code , which I am still working on. Also bear with me for the mistakes. Please feel free to correct it.
=====================================
import java.util.ArrayList;

public class programone
{
String Shape;
ArrayList<Integer> shapeA = new ArrayList<Integer>();
ArrayList<Integer> shapeB = new ArrayList<Integer>();
ArrayList<Integer> shapeC = new ArrayList<Integer>();
int arrayA[][] = {{100,50},{300,500}, {25, 45},{0,0}};
int arrayB[][] = {{100,50}};
int arrayC[][] = {{40,40},{100,50},{300,500}, {50, 100}, {0,0}};
int k=0;
int l=0;
int m=0;

public static void main(String args[]){
programone p1 = new programone();
p1.logic();
}

public void logic(){

for (int i = 0 ; i < arrayA.length ;i ++ )
{
for (int j =0 ; j <2 ; j ++,k++)
{
}
}
for (int i = 0 ; i < arrayB.length ;i ++ )
{
for (int j =0 ; j <2 ; j ++,l++)
{

}
}
for (int i = 0 ; i < arrayC.length ;i ++ )
{
for (int j =0 ; j <2 ; j ++,m++)
{
}
}

shapeA.removeAll(shapeB);
shapeC.retainAll(shapeA);

System.out.println("ShapeC has a resultant set : " + "{");
for (int y=0; y < shapeC.size(); y ++ )
{
if (y % 2 ==0)
{
System.out.println("{" + shapeC.get(y)
+","+ shapeC.get(y +1)+"}," );
}
}
System.out.println("}");
}
}