[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Sorting (HashSet)

Posted on 2011-10-04
26
Medium Priority
?
579 Views
Last Modified: 2012-05-12
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.
0
Comment
Question by:Johannne1
  • 12
  • 8
  • 6
26 Comments
 

Author Comment

by:Johannne1
ID: 36910957
I should precise that the sorting is desired on Id2 of the object. So if you have many
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.
0
 

Author Comment

by:Johannne1
ID: 36911009

Sorry the zone of this question is written Perl but it should be Java. I am looking for a java data structure and method.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36911105
>>
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());
	}
}

Open in new window

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 47

Expert Comment

by:for_yan
ID: 36911118
You should define Comparator which implements compare() method based on the second field
and then use m,ethod Collections.sort(Collection, Comparator)
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36911283
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.

        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());
    }

}

Open in new window


Output:
c  aa
a  b
c  d

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36911299
>>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
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36911394
This is with generics


        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());
        

    }

}

Open in new window


Ouptput:
c  aa
a  b
c  d

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36911430
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>
Set<Rule> rules = new TreeSet<Rule>(new Comparator<Rule>() {
	    public int compare(Rule r1, Rule r2) {
		return r1.getId2().compareTo(r2.getId2());
	    }
	});

Open in new window

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36911449
I guess, CEHJ just forgot to add: you'd probably be better off just sorting a List<Rule> as for_yan suggested  :)
0
 

Author Comment

by:Johannne1
ID: 36911453
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.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36911473
>>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
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36911480
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
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36911514


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());


    }

}

Open in new window

Ouput
c  aa
a  b
c  d

Open in new window

0
 

Author Comment

by:Johannne1
ID: 36912546
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.




0
 
LVL 47

Assisted Solution

by:for_yan
for_yan earned 2000 total points
ID: 36912562
I compiled and executed both
all three codes but try this one:

        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());
        

    }

}

Open in new window

0
 

Author Comment

by:Johannne1
ID: 36912649
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?
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36912675
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
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36912681
>>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
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36912735
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());
	}
    }

Open in new window

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36912737
CEHJ is right you can use the same anonymous comparator fas he sugggested for  List

       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);

        }

Open in new window


Output:

c  aa
a  b
c  d

Open in new window

0
 

Author Comment

by:Johannne1
ID: 36912790
Hi Yan,
I found my problem..

      .... MyComp.compare(MyComp.java:18)
      at java.util.Arrays.mergeSort(Arrays.java:1270)
      at java.util.Arrays.mergeSort(Arrays.java:1281)
      at java.util.Arrays.mergeSort(Arrays.java:1281)
      at java.util.Arrays.mergeSort(Arrays.java:1281)
      at java.util.Arrays.sort(Arrays.java:1210)
      at java.util.Collections.sort(Collections.java:159)

the line of code that it doesn't like is;

    return((PSXPmRule)r1).getId2().compareTo(((PSXPmRule)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!

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36912804
Sure, I meant this Rule as an example to be replaced by your Rule
Great, it works!
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36912810
>>return((PSXPmRule)r1).getId2().compareTo(((PSXPmRule)r2).getId2());

You can get rid of all that casting by genericizing the Comparator as in my  example (change the type accordingly)
0
 
LVL 47

Accepted Solution

by:
for_yan earned 2000 total points
ID: 36912915
CEHJ is right - this is absolutely clean example
how it works when MyComp is a separate class, all compiliing and executing
correctly.

Strange as it may seem, it is still a little bit tricky to do,
 just wanted to have it sitting here:


package comparatortest;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;


public class CompTest {

    public static void main(String[] args) {
        ArrayList<Rule> ar = new ArrayList<Rule>();
        ar.add(new Rule("a","b"));
        ar.add(new Rule("a","c"));
        ar.add(new Rule("e","aa"));

        Collections.sort(ar, new MyComp());

        for(Rule r: ar){
            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 implements Comparator<Rule> {

       public int compare(Rule r1, Rule r2){

           return r1.getId2().compareTo(r2.getId2());

       }

}

Open in new window

0
 
LVL 47

Expert Comment

by:for_yan
ID: 36912926
And thios is the output of the code in the  above post ID:36912915Author
e  aa
a  b
a  c

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 36913450
Johannne1, can you tell me why you ignored my comments please?
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
In this post we will learn different types of Android Layout and some basics of an Android App.
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
Suggested Courses
Course of the Month19 days, 18 hours left to enroll

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question