Johannne1
asked on
Sorting (HashSet)
sorting on second member of an object.
I have: an existing structure:
private Set<Rule> dAllRules = new HashSet<Rule>();
where the object Rule defined with five members
Id1 (String)
Id2 (String)
Id3 (String)
Id4 (String)
Id5 (String)
I have the existing code:
dAllRules.add(newObject);
example of data:
(first object)
Id1 = "ABC"
Id2 = "1"
Id3 = "hello1"
Id4 = "123"
Id5 = "5"
(second object)
Id1 = "DEF"
Id2 = "3"
Id3 = "hello2"
Id4 = "124"
Id5 = "1"
if i print or access objects in dAllRules
might print object #1 or object #2 since HashSet is not sorted.
I need to have the above data sorted on the second member of the object.
so that output/access would always be object #1 or object #2.
In other words I want to have a structure that contains objects of type Rule
that are sorted by the object's second memeber (Id2).
What is the easiest way to do this? I can add a new structure if I want.
I have: an existing structure:
private Set<Rule> dAllRules = new HashSet<Rule>();
where the object Rule defined with five members
Id1 (String)
Id2 (String)
Id3 (String)
Id4 (String)
Id5 (String)
I have the existing code:
dAllRules.add(newObject);
example of data:
(first object)
Id1 = "ABC"
Id2 = "1"
Id3 = "hello1"
Id4 = "123"
Id5 = "5"
(second object)
Id1 = "DEF"
Id2 = "3"
Id3 = "hello2"
Id4 = "124"
Id5 = "1"
if i print or access objects in dAllRules
might print object #1 or object #2 since HashSet is not sorted.
I need to have the above data sorted on the second member of the object.
so that output/access would always be object #1 or object #2.
In other words I want to have a structure that contains objects of type Rule
that are sorted by the object's second memeber (Id2).
What is the easiest way to do this? I can add a new structure if I want.
ASKER
Sorry the zone of this question is written Perl but it should be Java. I am looking for a java data structure and method.
>>
In other words I want to have a structure that contains objects of type Rule
that are sorted by the object's second memeber (Id2).
>>
You need something like
In other words I want to have a structure that contains objects of type Rule
that are sorted by the object's second memeber (Id2).
>>
You need something like
Set<Rule> rules = new TreeSet<Rule>(new Comparator<Rule>() {
public int compare(Rule r1, Rule r2) {
return r1.getId2().compareTo(r2.getId2());
}
}
You should define Comparator which implements compare() method based on the second field
and then use m,ethod Collections.sort(Collectio n, Comparator)
and then use m,ethod Collections.sort(Collectio
HashSet deso not have idea of the order - so you need to put to list before resorting
This is the way without generics:
I'll do with generics later.
Output:
This is the way without generics:
I'll do with generics later.
HashSet hs = new HashSet();
hs.add(new Rule("a","b"));
hs.add(new Rule("c","d"));
hs.add(new Rule("c","aa"));
ArrayList list1 = new ArrayList();
list1.addAll(hs);
Collections.sort(list1, new MyComp());
for (Object r : list1){
System.out.println((Rule) r);
}
public class Rule {
String s1;
String s2;
public Rule(String s1, String s2){
this.s1 = s1;
this.s2 = s2;
}
public String getString1() {return s1;}
public String getString2() {return s2;}
public String toString(){
return s1 + " " + s2;
}
}
import java.util.Comparator;
public class MyComp implements Comparator{
public int compare(Object r1, Object r2){
return (((Rule)r1).getString2()).compareTo(((Rule)r2).getString2());
}
}
Output:
c aa
a b
c d
>>so you need to put to list
You don't need to create yet another collection - just use a TreeSet in the first place, as i mentioned
You don't need to create yet another collection - just use a TreeSet in the first place, as i mentioned
This is with generics
Ouptput:
HashSet <Rule>hs = new HashSet<Rule>();
hs.add(new Rule("a","b"));
hs.add(new Rule("c","d"));
hs.add(new Rule("c","aa"));
ArrayList<Rule> list1 = new ArrayList<Rule>();
list1.addAll(hs);
Collections.sort(list1, new MyComp<Rule>());
for (Rule r : list1){
System.out.println( r);
}
class Rule {
String s1;
String s2;
public Rule(String s1, String s2){
this.s1 = s1;
this.s2 = s2;
}
public String getId1() {return s1;}
public String getId2() {return s2;}
public String toString(){
return s1 + " " + s2;
}
}
class MyComp<T> implements Comparator<T>{
public int compare(T r1, T r2){
return((Rule)r1).getId2().compareTo(((Rule)r2).getId2());
}
}
Ouptput:
c aa
a b
c d
Sorry, there was a typo in my code - should have been as below.
Another thing: if id2 is not unique, you can't use the TreeSet and you'd probably be better off just sorting a List<Rule>
Another thing: if id2 is not unique, you can't use the TreeSet and you'd probably be better off just sorting a List<Rule>
Set<Rule> rules = new TreeSet<Rule>(new Comparator<Rule>() {
public int compare(Rule r1, Rule r2) {
return r1.getId2().compareTo(r2.getId2());
}
});
I guess, CEHJ just forgot to add: you'd probably be better off just sorting a List<Rule> as for_yan suggested :)
ASKER
Hi CEHJ,
Yeah you are right, id2 is not unique, actuall in an object, what is unique is
id1+id2, so you could have an object 1 with 'first'+'one" and object 2 with 'second'+'one',
I am looking throught all the suggestions.
Yeah you are right, id2 is not unique, actuall in an object, what is unique is
id1+id2, so you could have an object 1 with 'first'+'one" and object 2 with 'second'+'one',
I am looking throught all the suggestions.
>>I guess, CEHJ just forgot to add: you'd probably be better off just sorting a List<Rule> as for_yan suggested :)
Well it seemed to me you were suggesting to move between a Set and a List. I'm saying - forget the Set
Well it seemed to me you were suggesting to move between a Set and a List. I'm saying - forget the Set
If you originallly already have stuff in HashSet move it to list, if you are just
collecting them - certainly forget the set and start with the List - especially if you have
objects with the same id2
collecting them - certainly forget the set and start with the List - especially if you have
objects with the same id2
If you are in the position to modify the class Rule just implement Comparable
and it will be the simplest like below:
ArrayList<Rule> list1 = new ArrayList<Rule>();
list1.add(new Rule("a","b"));
list1.add(new Rule("c","d"));
list1.add(new Rule("c","aa"));
Collections.sort(list1);
for (Rule r : list1){
System.out.println( r);
}
class Rule implements Comparable<Rule> {
String s1;
String s2;
public Rule(String s1, String s2){
this.s1 = s1;
this.s2 = s2;
}
public String getId1() {return s1;}
public String getId2() {return s2;}
public String toString(){
return s1 + " " + s2;
}
public int compareTo( Rule r){
return s2.compareTo(r.getId2());
}
}
Ouputc aa
a b
c d
ASKER
Hi Yan,
Your list suggestion (as well as CEHJ also suggested) would work. The only probably is I can't get comparator to work.
I am able to do: add the hashset to the array list.
ArrayList list1 = new ArrayList();
list1.addAll(hs);
but the myComp() is causing problems.
Collections.sort(list1, new MyComp());
I can't seem to be able to get the comparator to work.
Your list suggestion (as well as CEHJ also suggested) would work. The only probably is I can't get comparator to work.
I am able to do: add the hashset to the array list.
ArrayList list1 = new ArrayList();
list1.addAll(hs);
but the myComp() is causing problems.
Collections.sort(list1, new MyComp());
I can't seem to be able to get the comparator to work.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yan, I am on the case, I am trying these..
I was able to add to the class Rule but for the class myComp to I put this in a separate file?
I was able to add to the class Rule but for the class myComp to I put this in a separate file?
It does not matter - if you declaer it public you should put it in separate file MyComp.java
or you can purt in the same file - just
class MyComp
wuithout paublic
or you can purt in the same file - just
class MyComp
wuithout paublic
>>The only probably is I can't get comparator to work.
The Comparator i posted above works fine - i tested it. You can use the same one for any kind of Collection
The Comparator i posted above works fine - i tested it. You can use the same one for any kind of Collection
If you want it as a standalone class (easier to work with) then it's
private class MyComp implements Comparator<Rule> {
public int compare(Rule r1, Rule r2) {
return r1.getId2().compareTo(r2.getId2());
}
}
CEHJ is right you can use the same anonymous comparator fas he sugggested for List
Output:
ArrayList<Rule> list1 = new ArrayList<Rule>();
list1.add(new Rule("a","b"));
list1.add(new Rule("c","d"));
list1.add(new Rule("c","aa"));
Collections.sort(list1, new Comparator<Rule>() {
public int compare(Rule r1, Rule r2) {
return r1.getId2().compareTo(r2.getId2());
}
});
for (Rule r : list1){
System.out.println( r);
}
Output:
c aa
a b
c d
ASKER
Hi Yan,
I found my problem..
.... MyComp.compare(MyComp.java :18)
at java.util.Arrays.mergeSort (Arrays.ja va:1270)
at java.util.Arrays.mergeSort (Arrays.ja va:1281)
at java.util.Arrays.mergeSort (Arrays.ja va:1281)
at java.util.Arrays.mergeSort (Arrays.ja va:1281)
at java.util.Arrays.sort(Arra ys.java:12 10)
at java.util.Collections.sort (Collectio ns.java:15 9)
the line of code that it doesn't like is;
return((PSXPmRule)r1).getI d2().compa reTo(((PSX PmRule)r2) .getId2()) ;
but really what it was I already had class Rule and I was re-declarng s1 and s2 instead of
using my existing item1 and item2 of my object.
It is working very well, by implementing comparable in existing Rule class or declaring separate
file or inner class.
thanks a lot!
I found my problem..
.... MyComp.compare(MyComp.java
at java.util.Arrays.mergeSort
at java.util.Arrays.mergeSort
at java.util.Arrays.mergeSort
at java.util.Arrays.mergeSort
at java.util.Arrays.sort(Arra
at java.util.Collections.sort
the line of code that it doesn't like is;
return((PSXPmRule)r1).getI
but really what it was I already had class Rule and I was re-declarng s1 and s2 instead of
using my existing item1 and item2 of my object.
It is working very well, by implementing comparable in existing Rule class or declaring separate
file or inner class.
thanks a lot!
Sure, I meant this Rule as an example to be replaced by your Rule
Great, it works!
Great, it works!
>>return((PSXPmRule)r1).ge tId2().com pareTo(((P SXPmRule)r 2).getId2( ));
You can get rid of all that casting by genericizing the Comparator as in my example (change the type accordingly)
You can get rid of all that casting by genericizing the Comparator as in my example (change the type accordingly)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
And thios is the output of the code in the above post ID:36912915Author
e aa
a b
a c
Johannne1, can you tell me why you ignored my comments please?
ASKER
objects,
object 1 has Id2=4, object 2 Id2=3, object3 Id2=1, Object4 Id=6
the sorting occurs on Id2, so correct order is:
Object 3, Object2, Object1, and Object 4.