czwartek, 22 stycznia 2009

Java Killers #10

Dziejszy Java Killer prosty i niezbyt wyrafinowany. Ależ jak wiele bólu może dostarczyć, gdy taki kod dostanie się na produkcje, wie tylko programista, który to przeżył...
No dobra, nie jest, aż tak tragicznie, ale mimo wszystko boli. Pytanie na dziś, co wypisze na konsoli działanie poniższego programu:


public static void main(String[] args) {

SortedSet names = new TreeSet();

names.add("Gąskalska Anna");
names.add("Enigmatyczna Jola");
names.add("Ambroży Tomasz");
names.add("Ędward Ącki");

System.out.println(names);

}



Odpowiedzi możliwych kilka, a prawdziwa jak zwykle tylko jedna:

A) [Gąskalska Anna]
B) [Ambroży Tomasz, Enigmatyczna Jola, Gąskalska Anna, Ędward Ącki]
C) [Ambroży Tomasz, Enigmatyczna Jola, Ędward Ącki, Gąskalska Anna ]
D) [Ambroży Tomasz, Ędward Ącki, Enigmatyczna Jola, Gąskalska Anna ]
E) java.util.SortedSet@122cdb6
F) błąd kompilacji



Otóż okazuje się, że prawidłowa odpowiedź to:
B) [Ambroży Tomasz, Enigmatyczna Jola, Gąskalska Anna, Ędward Ącki]

Jak to!? Przecież miała być lista posortowana alfbatecznie! Co jest grane? Cóż, program zachowuje się zgodnie ze specyfikacją, gdzie wyraźnie czytamy:

Method comparesTo (...) compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings. (...) Method compareTo returns the difference of the two character values at position k in the two string -- that is, the value this.charAt(k)-anotherString.charAt(k).


A jak przyjrzymy się znakom Unicode, polskie krzaczki mają wartości o niebo większe od standardowych literek z alfabetu łacińskiego. I tak ę, ą, ć, ń, ż, ź, ś, ó oraz ł będzie zawsze stać za całą resztą abecadła.
Miejscie to prosze na uwadze, sortując swoje listy :)

13 komentarzy:

Michał Mech pisze...

A co by było jakbyś napisał tak:

names.add(new String("Gąskalska Anna", "ISO-8859-2"));
names.add(new String("Enigmatyczna Jola", "ISO-8859-2"));
names.add(new String("Ambroży Tomasz", "ISO-8859-2"));
names.add(new String("Ędward Ącki", "ISO-8859-2"));

Odnoszę wrażenie, że mogłoby być OK.

Paweł pisze...

String nie ma takiego konstruktora

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html

Paweł pisze...

@michał mech: nota bene fajnie twoj blog sie zaczyna, tez bede sie przymierzal do seama ale czekam na wydanie oficjalnej ksiazki w lutym 2009

Unknown pisze...

Zgadłem! Zgdałem! Ale chyba tylko dlatego, że przeczuwałem jakieś coś, co przeczy zdrowemu (polskiemu) rozsądkowi. Po przeczytaniu wyjaśnienia zrobiło się klarowniej. Dzięki!

Paweł pisze...

@jacek: milo mi ze coraz czesciej zagladasz tutaj :)

Koziołek pisze...

Jak ja lubię ten problem. Zresztą jest to utrapienie wielu mniej doświadczonych programistów, którzy jeszcze nie spotkali się z "Nowym alfabetem Języka Polskiego". Najweselej jest jednak jak za sortowanie tego typu biorą się innostriency :)

Paweł pisze...

@Michał Mech: tak to ta ksiazka, czekam na nia z niecierpliwoscia

pytanie czy jak w koncu Ędward Ącki wystartuje w wyborach, to czy bedzie dobrze posortowany na liście potencjalnych kandydatów ;)

Michał Mech pisze...

Paweł książka ta jest już dostępna dzięki Safari Early Access: http://my.safaribooksonline.com/9780137151660

Też niecierpliwie na nią czekam. Z moich obecnych obserwacji jedną z leszych pozycji wydaje się być ... oficjalna dokumentacja :)

Macieq pisze...

Co ciekawe:

SortedSet names = new TreeSet(Collator.getInstance(new Locale("pl_PL")));

names.add("Gąskalska Anna");
names.add("Enigmatyczna Jola");
names.add("Ambroży Tomasz");
names.add("Ędward Ącki");

System.out.println(names);

daje:

[Ambroży Tomasz, Ędward Ącki, Enigmatyczna Jola, Gąskalska Anna]

czyli też niezbyt ;-)

Anonimowy pisze...

Akurat ten killer byl z tych prostych, żeby nie powiedziec ze byl najprostszy z dotychczasowo opublikowanych:)

Unknown pisze...

new TreeSet(Collator.getInstance(new Locale("pl_PL")));

Byłoby miło gdyby to działało poprawnie... Jest jakaś możliwość zrobienia żeby było dobrze?

a pisze...

No to jeszcze prawidłowe rozwiązania, a raczej oczekiwane rozwiązanie - jak to napisać, by sortowanie uwzględniało lokale?
Nie wiem, to i chętnie się dowiem :)

Tomasz Bartczak
Racjonalny Developer

Paweł pisze...

Jak pokazał Macieq zwykły Collator też nie działa poprawnie (mimo ze podobno "The Collator class performs locale-sensitive String comparison".

Najlepiej napisać chyba na szybko regułę do polskiego języka i wykorzystać RuleBasedCollator IMHO

http://java.sun.com/j2se/1.4.2/docs/api/java/text/RuleBasedCollator.html