wood burning stoves 2.0*
The moose likes Java in General and the fly likes HashSet problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "HashSet problem" Watch "HashSet problem" New topic
Author

HashSet problem

Vinay Naga
Greenhorn

Joined: May 16, 2008
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.add(arrayA);
shapeB.add(arrayB);
shapeC.add(arrayC);

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.

Thanks for your help,
Vinay
Jeanne Boyarsky
internet detective
Marshal

Joined: May 26, 2003
Posts: 30309
    
150

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.


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19670
    
  18

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:


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Vilmantas Baranauskas
Ranch Hand

Joined: Dec 20, 2006
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[]>();

...

shapeA.addAll(Arrays.asList(arrayA));
shapeB.addAll(Arrays.asList(arrayB));
shapeC.addAll(Arrays.asList(arrayC));



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


Author of <a href="http://www.newsinjector.com" target="_blank" rel="nofollow">NewsInjector</a>
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19670
    
  18

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

Joined: Dec 20, 2006
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

Joined: Oct 27, 2005
Posts: 19670
    
  18

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

Joined: May 16, 2008
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)�

Please provide all code.
===================================

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++)
{
shapeA.add(k,arrayA[i][j]);
}
}
for (int i = 0 ; i < arrayB.length ;i ++ )
{
for (int j =0 ; j <2 ; j ++,l++)
{

shapeB.add(l,arrayB[i][j]);
}
}
for (int i = 0 ; i < arrayC.length ;i ++ )
{
for (int j =0 ; j <2 ; j ++,m++)
{
shapeC.add(m,arrayC[i][j]);
}
}

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("}");
}
}
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: HashSet problem