Win a copy of Testing JavaScript Applications this week in the HTML Pages with CSS and JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Liutauras Vilda
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • fred rosenberger
  • salvin francis
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Carey Brown

TreeMap Sorting

 
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello ,

I have a little bit complicated TreeMap problem, so i hope i'm clear in my explanation.

I have a TreeMap that accepts words & their count, like this :

Now i want to fill this map with the following words and their count : {car, apple, Dog, Apple}
So for the defined map(wordsCount) its values will appear like this :

But i don't want this order, i want to skip the Case Sensitivity ordering, to be like this :

I tried to use this Comparator :

But this will produce the following :

Sorry for the complicated Explanation .... I hope i'm clear enough !!
Any solution ?
 
Ranch Hand
Posts: 624
IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What you are running into is the fact that the Java uses the "Natural Order" for comparing and sorting objects. And with Strings, that results in what is sometimes referred to as "ASCIIbetical" ordering rather than alphabetical ordering. There is this definition of ASCIIbetical. There is also the blog entry Alphabetical != ASCIIbetical which rants about the issue, but does not provide much concrete help solving it.

I thought I saw a utility class once that had either a sort method or compare method that resulted in true alphabetical sorting, but can't seem to remember where at this point. Best I can suggest is to do some Goggling and see if you can find an implementation of such a thing, or painfully write your own. The problem becomes what happens when you move past English characters? Even simple accented characters, let alone glyphs from other languages. The answer to this may depend on what the potential use of your application is an whether it needs to be internationalized. But even in English you run into the issue in words such as resume (to start again) versus résumé (career summary).

Maybe someone else here knows of a sort or compare implementation that results in true alphabetical order rather than grouping uppercase and lower case words.

 
author
Posts: 23879
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Best I can suggest is to do some Goggling and see if you can find an implementation of such a thing, or painfully write your own.



Why would you really need google for this? It's pretty easy to write a comparator that does this. In fact, I just wrote it during lunch -- and it took 10 minutes.

The problem becomes what happens when you move past English characters? Even simple accented characters, let alone glyphs from other languages. The answer to this may depend on what the potential use of your application is an whether it needs to be internationalized.



Yea. This is true. Edge conditions are a pain ...

Henry
 
Marshal
Posts: 25682
69
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Henry Wong wrote:Why would you really need google for this? It's pretty easy to write a comparator that does this. In fact, I just wrote it during lunch -- and it took 10 minutes.



Are you saying that you rewrote the existing Comparator String.CASE_INSENSITIVE_ORDER?
 
Henry Wong
author
Posts: 23879
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:

Henry Wong wrote:Why would you really need google for this? It's pretty easy to write a comparator that does this. In fact, I just wrote it during lunch -- and it took 10 minutes.



Are you saying that you rewrote the existing Comparator String.CASE_INSENSITIVE_ORDER?



No. This is not what the OP wanted. The comparator loops through the string, and for each character, does a case insensitive check. However, if the characters are "equal", it further does a case sensitive check (in reverse, as requirement is for lower case to come first). Only when characters are truely equal does it moves onto the next character.

Henry
 
Paul Clapham
Marshal
Posts: 25682
69
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
More like a RuleBasedCollator, then. Although it probably would have taken nearly 10 minutes to configure one of those, too.
 
Hesham Gneady
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Emmm ... Thanks for the answers everyone.
If i understand you well Henry, you mean something like this :
 
Henry Wong
author
Posts: 23879
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

If i understand you well Henry, you mean something like this :



Close. Something like that. But you need to do the comparison on a character basis -- which means that you also have to add a loop too.

Henry
 
Hesham Gneady
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

But you need to do the comparison on a character basis


I think the solution i mentioned works okay in my program. But i need to understand why do i need to do the comparison on a character basis ? What's the idea ?
 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
try this

class WordsCountComparator implements Comparator<String> {

public int compare(String o1, String b) {
return 1;
}
}

compare method Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
If you want to get the output in same order as input then you have to override the compare method that will always return 1.
 
Sheriff
Posts: 21974
106
Eclipse IDE Spring VI Editor Chrome Java Ubuntu Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hesham, your code looks just fine. You can make it a little bit faster by only going through the entire strings for the second time if needed; now you always go through the entire strings twice (once with equals, once with compareTo / compareToIgnoreCase). The following can solve that:
It will still do the same (use compareTo if the strings are equal ignoring the case, otherwise compareToIgnoreCase) but it only goes through the string a second time if the strings are equal ignoring the case.

anandhi mohan wrote:try this



compare method Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
If you want to get the output in same order as input then you have to override the compare method that will always return 1.


Never ever ever return a constant from compare. It will make your ordering totally unpredictable ("apple" would be larger than "Apple", but "Apple" would be larger than "apple"), and even worse: "apple" would be larger than "apple"!

If you need to keep insertion order, you shouldn't use a TreeMap but a LinkedHashMap instead. If you need to keep insertion order and allow duplicates (what your code would do), use a List.
 
Hesham Gneady
Ranch Hand
Posts: 66
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ahah ... I've got what you mean Rob. You're right.
I already use this to read 1000s of words so this will be very useful.

Thanks a lot
 
Ranch Hand
Posts: 856
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Rob Prime wrote:Never ever ever return a constant from compare.



Rob i am using this code, to sort Object properties, so i am returning constants here.
Is it this a bad idea ?
 
Marshal
Posts: 69889
278
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That looks all right provided you use these rules
  • A long word is always "greater" than a short word.
  • Two words the same length are sorted in ASCIIbetical order
  •  
    Campbell Ritchie
    Marshal
    Posts: 69889
    278
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It won't sort backwards in alphabetic order, however.
     
    Amandeep Singh
    Ranch Hand
    Posts: 856
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    it will sort in reverse order because i am doing this :

    I am comparing the o2 first and then o1.



    instead of :

     
    Rob Spoor
    Sheriff
    Posts: 21974
    106
    Eclipse IDE Spring VI Editor Chrome Java Ubuntu Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Amandeep Singh wrote:

    Rob Prime wrote:Never ever ever return a constant from compare.



    Rob i am using this code, to sort Object properties, so i am returning constants here.
    Is it this a bad idea ?


    No, this looks just fine. What I meant was return the same constant in all cases (like the "return 1;" from Anandhi's post). Returning -1 in one case, 1 in the other case is just fine. In fact, that is how Integer and Long are compared. From java.lang.Integer:
    Nothing wrong with that.
     
    Consider Paul's rocket mass heater.
      Bookmark Topic Watch Topic
    • New Topic