Order Sztandaru Pracy i klasy

Jestem trochę nowy w Guava i to jest styl. Na pewno to kopię, ale jedną rzeczą, o którą ciągle się potkam, jest kolejność łańcuchowych metod. Tam, gdzie wydaje mi się, że ten problem najbardziej dotyczy używania compound Ordering s. muszę ciągle zadawać sobie pytania typu:

  • gdzie idzie natural?
  • gdzie idzie nullFirst (lub ostatni)?
  • Który nullsFirst robi co? (W poniższym przykładzie jeden dla hosta, jeden dla nazwiska, jeden dla imienia?)

Oto przykład jednego, nad którym właśnie pracowałem. Wygląda to uciążliwie i nie jestem pewna, czy dobrze to wszystko poukładałam. Mam kilka Junitów do przetestowania tego, i wydaje się w porządku, ale zawsze są te dziwne przypadki graniczne.

Ordering<Host> lastNameThenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
    public String apply(Host host) {
        return host.getLastName();
    }}).compound(Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
    public String apply(Host host) {
        return host.getFirstName();
    }})).nullsFirst();

Jeśli chodzi o rzeczywiste pytanie: czy istnieje dobrze zdefiniowana zasada, jak te rzeczy są wykonywane? Wydaje się, że ostatni do pierwszego, ale mam problem z mówieniem tego.

Edit: chciałem tylko zwrócić uwagę na duży, brzydki kod, który próbowałem zastąpić:

    Ordering<Host> ordering2 = new Ordering<Host>() {
        public int compare(Host host1, Host host2) {
            if (host1 == null || host2 == null) {
                return host1 == host2 ? 0 : ((host1 == null) ? -1 : 1); 
            }
            if(host1.getLastName() != null || host2.getLastName() != null){
                if (host1.getLastName() == null) {
                    return -1;
                } else if (host2.getLastName() == null) {
                    return 1;
                }

                if (host1.getLastName().compareTo(host2.getLastName()) != 0) {
                    return host1.getLastName().compareTo(host2.getLastName());
                }
            }

            if (host1.getFirstName() == null) {
                return -1;
            } else if (host2.getFirstName() == null) {
                return 1;
            }

            return host1.getFirstName().compareTo(host2.getFirstName());
        }};
Author: Ray, 2011-02-11

3 answers

Każde wywołanie łańcuchowe "zawija" poprzednie zlecenie w nowe, więc masz rację, kolejność wykonania może być traktowana jako "wstecz".

Napisałem i przejrzałem klasę zamawiającą i nadal regularnie muszę się zatrzymać i podrapać głową nad poprawnym przeplotem nullsFirst (), oraz onResultOf() i reverse()!

 11
Author: Kevin Bourrillion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-11 18:55:08

Myślę, że to co robisz jest poprawne, ale strasznie brzydkie. Spróbuj tego dla czytelności:

Użyj Enum

Przenieś funkcje do enum implementującego Function<Host, String>. Każda z pozycji enum może dostarczyć własną implementację.

enum HostFunctions implements Function<Host, String>{
    GETFIRSTNAME{

        @Override
        public String apply(final Host host){
            return host.getFirstName();
        }
    },
    GETLASTNAME{

        @Override
        public String apply(final Host host){
            return host.getLastName();
        }
    }

}

Wpisz swój kod

Teraz odwołaj się do tych funkcji enum i odpowiednio wciśnij kod. Tak to będzie wyglądało:

final Ordering<Host> orderingByLastAndFirstName =
    Ordering
        .natural()
        .nullsFirst()
        .onResultOf(HostFunctions.GETLASTNAME)
        .compound(
            Ordering
                .natural()
                .nullsFirst()
                .onResultOf(HostFunctions.GETFIRSTNAME))
        .nullsFirst();
To czyni wszystko bardziej zrozumiałym.

Konfiguracja IDE

Odnośnie poprawne wcięcie (przynajmniej jeśli używasz Eclipse), zobacz to pytanie:

Jak wciąć płynny interfejs wzór "poprawnie" z eclipse?

Enums as Functions

W odniesieniu do enum: nazywa się to wzorem Singletona enum. Faceci z guawy używają go w bazie kodów. Poczytaj o tym na Wikipedii lub w efektywnej Javie , poz. 3. Chociaż oba te źródła mówią o enumach jednostkowych, podejście jest prawie ja też.

 23
Author: Sean Patrick Floyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:33:18

Poniżej chciałbym to zrobić, zakładając, że musisz być w stanie obsłużyć null hosty, imiona i nazwiska. Dla mnie wygląda na to, że nie null imię i nazwisko powinno być wymogiem klasy Host. Generalnie należy unikać zezwalania kolekcjom na umieszczanie obiektów null.

Ordering<Host> lastNameFirstNameOrdering = new Ordering<Host>() {
  @Override public int compare(Host left, Host right) {
    return ComparisonChain.start()
      .compare(left.getLastName(), right.getLastName(), Ordering.natural().nullsFirst())
      .compare(left.getFirstName(), right.getFirstName(), Ordering.natural().nullsFirst())
      .result();
  }
}.nullsFirst();

Alternatywnie, wziąłbym podejście podobne do Seana, ale rozbić rzeczy na czytelność.

Ordering<Host> lastNameOrder = Ordering.natural().nullsFirst()
    .onResultOf(Host.LAST_NAME);
Ordering<Host> firstNameOrder = Ordering.natural().nullsFirst()
    .onResultOf(Host.FIRST_NAME);
Ordering<Host> orderingByLastAndFirstName =
     lastNameOrder.compound(firstNameOrder).nullsFirst();

Pamiętaj, że możesz również te indywidualne zamówienia statyczne końcowe pola klasy, co pozwala na łatwe użycie ich w dowolnym miejscu podczas sortowania jak Host.LAST_NAME_ORDER.

 9
Author: ColinD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-11 21:00:27