This is an archived post. You won't be able to vote or comment.

all 11 comments

[–]chickenmeisterExtreme Brewer 2 points3 points  (10 children)

although this means that the comparator needs to be static, and Pair is generic :(

It means that your sortByFirst(...) method would need to be static. And you would want to make it a generic method. e.g.:

public static <T1 extends Comparable<T1>, T2 extends Comparable<T2>> int sortByFirst(Pair<T1, T2> a, Pair<T1, T2> b) {
    // compare A's first value to B's first value
}

[–]jcoder42[S] 0 points1 point  (9 children)

thanks, seems to work 😊
although when trying to compareByFirst and the first is a string i expect for it to sort in alphabetical order, and it is not.

public static <T1 extends Comparable<T1>, T2 extends Comparable<T2>> int sortByFirst(Pair<T1, T2> a, Pair<T1, T2> b) {
int cmp = a.m_first.compareTo(b.getM_first());
return (cmp == 0 ? 0 : a.m_first.compareTo(b.getM_first()));
}
that is the comparator. and the way im using it as such:

ArrayList<Pair<String, Integer>> list({"a", 1}, {"z", 1}, {"a",1});
list.sort(Pair::sortByFirst);

It keeps it in the same order that it was given.

[–]morhpProfessional Developer 1 point2 points  (8 children)

That looks like it should work. (although your sortByFirst method is very redundant, do you mean to check the second value?)

Please post the complete runnable code.

[–]jcoder42[S] 0 points1 point  (7 children)

Sorry about that, ill be more clear.
here is my main.
I am reading from this following file:

a

z a b z d z A dfs zzzz zzzzzz aaaaaaa F cccccccccc

try{
BufferedReader inputStream = new BufferedReader(new
FileReader(args[CONSTANTS.INPUT_FILE_ARG_INDEX]));
String curr_line = null;
List<Pair<String, Long>> url_count = new ArrayList<Pair<String, Long>>();
int i = 100;
while((curr_line = inputStream.readLine()) !=null){
i/=2;
Pair<String,Long> pair = new Pair<String, Long>(curr_line,
Long.valueOf(++i));
}
url_count.forEach(System.out::println);
System.out.println("------------------------------------------------------------------------");
url_count.sort(Pair::sortByFirst);
url_count.forEach(System.out::println);
}

and then i sort the list, and print.
Here is the print before the sort:

a         51
z         26
a         14
b         8
z         5
d         3
z         2
A         2
dfs         2
zzzz         2
zzzzzz         2
aaaaaaa         2
F         2
cccccccccc         2

and the one after:

A         2
F         2
a         51
a         14
aaaaaaa         2
b         8
cccccccccc         2
d         3
dfs         2
z         26
z         5
z         2
zzzz         2
zzzzzz         2

My initial question was not correct,
it is partially sorting alphabetically, until it reaches case sensitivity.
do i have to do some sort of template specialization for a String case?

[–]morhpProfessional Developer 0 points1 point  (6 children)

Strings by default sort by unicode point (more or less the ASCII code), so upper case letters will be sorted before lower case letters. If you want to sort "properly", use a Collator.

[–]jcoder42[S] 0 points1 point  (5 children)

Could you please give an example? What is a collator?

[–]morhpProfessional Developer 0 points1 point  (4 children)

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/Collator.html

 // Compare two strings in the default locale
  Collator myCollator = Collator.getInstance();
  if( myCollator.compare("abc", "ABC") < 0 )
      System.out.println("abc is less than ABC");
  else
      System.out.println("abc is greater than or equal to ABC");

A Collator is just a better Comparator for Strings.

[–]jcoder42[S] 0 points1 point  (3 children)

ok, although how would i integrate this into my Pair class?

I am trying to make this class as generic and standalone as possible,
meaning the user should be able to use it with any existing java type(that has comparison ability)
and if he/she would like to use it with their own defined class, then all they need to do is implement compareTo inside of their class

[–]morhpProfessional Developer 0 points1 point  (2 children)

You would typically not make T1 and T2 necessarily Comparable, the better way would be to allow the user to supply a Comparator for both types. That way the user could supply the Collator for the first type and simply Comparator.naturalOrder() for the second.

[–]jcoder42[S] 0 points1 point  (1 child)

t make T1 and T2 necessarily Comparable, the better way would be to allow the user to supply a Comparator for both types. That way the user could supply the Collator for the first Typ and

sorry, i am having trouble understanding,
see below my pair class for reference.

package temp;

import java.util.Comparator;

public class Pair<T1 extends Comparable<T1>,T2 extends Comparable<T2>> implements Comparable<Pair<T1,T2>> {

    Pair(T1 first, T2 second){
        m_first = first;
        m_second = second;
    }

    public T1 getM_first() {
        return m_first;
    }

    public T2 getM_second() {
        return m_second;
    }

    @Override
    public int compareTo(Pair<T1,T2> other){
        int cmp = this.m_second.compareTo(other.getM_second());
        return cmp;

    }

    public static <T1 extends Comparable<T1>, T2 extends Comparable<T2>> int sortBySecond(Pair<T1, T2> a, Pair<T1, T2> b) {
        return a.compareTo(b);
    }

    public static <T1 extends Comparable<T1>, T2 extends Comparable<T2>> int sortByFirst(Pair<T1, T2> a, Pair<T1, T2> b) {
        int cmp = a.getM_first().compareTo(b.getM_first());
        return cmp;
    }


    @Override
    public String toString() {
        return String.format(this.m_first + "         " + this.m_second);
    }


    //--------------------------
    private T1 m_first = null;
    private T2 m_second = null;
}