Сортировать объект по другому - PullRequest
1 голос
/ 22 апреля 2010

Вот сделка:

В моей заявке есть объекты публикации. У меня также есть Голосовать по объектам (forOrAgainst, автор, связанная публикация)

Я хочу отсортировать публикацию по дате, названию ... а также по количеству голосов.

Я не могу напрямую отсортировать свой список публикаций, поскольку у меня нет числа голосов в этом списке. Как отсортировать список публикаций, не добавляя метод к объекту публикации.

Как лучше всего связать их?

Должен ли я вернуть хэш-карту? набор деревьев? массив?

Теперь у меня в голове немного грязно ...

Ответы [ 4 ]

3 голосов
/ 22 апреля 2010

Винс прав - здесь рекомендуется использовать Компаратор. В вашем случае, компаратор statefull ; во время строительства вы должны предоставить ему данные о количестве голосов различных предметов (поскольку они не являются частью предметов).

Collections.sort (..) - хорошая идея, если вы хотите отсортировать список. Если, с другой стороны, вы решили поместить свои элементы в какой-то SortedSet (или SortedMap), убедитесь, что голоса (и другие поля, используемые компаратором) остаются без изменений. В противном случае структура данных будет повреждена и больше не будет сохранять правильный порядок элементов.

3 голосов
/ 22 апреля 2010

Вот пример использования Comparator для сортировки на основе внешних критериев:

import java.util.*;

class VoteComparator implements Comparator<String> {
    final Map<String, Integer> tally;
    VoteComparator(Map<String, Integer> tally) {
        this.tally = tally;
    }
    @Override public int compare(String pub1, String pub2) {
        int v1 = tally.get(pub1);
        int v2 = tally.get(pub2);
        return
           (v1 < v2) ? -1 :
           (v1 > v2) ? +1 :
           0;
    }           
};

Для простоты здесь используется String; Вы хотите отсортировать Publication в своем приложении. Здесь также используется простой int для подсчета голосов, но, по сути, должна существовать служба подсчета, которая дает вам, учитывая Publication, то, что составляет Vote счет.

Примечание: английский не мой родной язык, поэтому, возможно, слово "подсчет" не подходит для него, но в основном это своего рода регистратор голосов, регистратор голосов, по сути, карта между объектом и тем, сколько голосов он получает .

Затем вы можете сортировать, используя, скажем, TreeSet.

public class SortExample {
    public static void main(String[] args) {
        Map<String, Integer> tally = new HashMap<String, Integer>();
        tally.put("foo", 42);
        tally.put("bar", 13);
        tally.put("Fizz", 3);
        tally.put("Buzz", 5);
        tally.put("FizzBuzz", 15);

        Comparator<String> voteComparator = new VoteComparator(tally);
        SortedSet<String> sortedByVote = new TreeSet<String>(voteComparator);
        sortedByVote.addAll(tally.keySet());
        for (String pub: sortedByVote) {
            System.out.println(pub + " (" + tally.get(pub) + " votes)");
        }
    }
}

Это печатает:

Fizz (3 votes)
Buzz (5 votes)
bar (13 votes)
FizzBuzz (15 votes)
foo (42 votes)
3 голосов
/ 22 апреля 2010

Решение состоит в том, чтобы реализовать интерфейс Comparator (http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html),, который затем можно использовать, например, для функции Collections.sort (Список списков, Компаратор-компаратор) (http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator).

).
0 голосов
/ 22 апреля 2010

Я бы посоветовал изменить структуру вашего класса на что-то вроде:

public class Publication implements Comparable<Publication> {
    private String title;
    private Date date;
    // etc....
    private Collection<Vote> votes;

    // Possibly even:
    private int upVotes;
    private int downVotes;

    // Constructors etc.

   // Handle votes here.
   public void addVote(Vote vote) {
       votes.add(vote);
       if (vote.isUpVote()) {
           upVotes++;
       } else {
           downVotes++;
       }
   }

   // Other methods for handling whatever you need to do.


   public int compareTo(Publication other) {
       // Now in here you can implement your sorting logic and have direct access to number of votes.
       // If you decide not to implement the counters of upVotes and downVotes then you will need to iterate over your votes collection and count them each time you do a compare, so it might be worth doing it to be more efficient.  You just have to make sure that any methods you add that affect the votes collection also updates the counters.
   }

}

public class Vote {
    private boolean isUpVote;
    private String author;
    // No need for a link to the publication now.

    public boolean isUpVote() {
        return isUpVote;
    }

    // etc.
}

Теперь, где бы вы ни хранили свои публикации, вы можете просто:

Collections.sort(publications);

при условии, что ваша коллекция публикаций представляет собой список, т.е.

List<Publication> publications = new ArrayList<Publication>();

Помните (как сказал Эяль), если вы измените состояние своих публикаций (то есть измените голоса или что-то еще, что влияет на порядок сортировки), вам придется прибегнуть к помощи, это не произойдет автоматически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...