2010-04-22 3 views
1

Сделка:Отсортировать объект по-другому

У меня есть объекты для публикации в моем приложении. У меня также есть Vote objet (forOrAgainst, author, linkedPublication)

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

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

Каков наилучший способ их связывания?

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

Это своего рода грязный в моем мозгу сейчас ...

+0

Здесь также бесполезно. Как насчет уточнения? –

ответ

3

Вот пример использования 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) 
+1

'Tally' - хорошее слово :). –

3

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

+0

Проблема в том, что я не могу сортировать непосредственно мой список публикаций, так как у меня нет моего голосования в этом списке. – user284295

+0

@ kevinb92: см. Мой ответ, например, как вы можете использовать 'Comparator' для сортировки на основе внешних критериев. – polygenelubricants

+0

Чтобы завершить, если вы хотите изменить порядок в зависимости от того, какие критерии вы хотите использовать (дата, название, количество голосов ...), вам просто нужно реализовать компаратор для каждого критерия. – Vinze

3

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

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

+0

+1 о неизменности всего, что используется в качестве ключа к карте. И, как сказано в другом вопросе, функция сортировки должна быть вызвана каждый раз, когда изменяются критерии заказа (в этом случае новые голоса). – Vinze

0

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

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); 

assumin г ваша коллекция публикаций является список, т.е.

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

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

+0

Это кажется мне плохой идеей. Пусть 'Публикация' не обращает внимания на то, сколько« Голосовать »она получает. По возможности, он должен быть непреложным. Такая статистическая метрика является изменчивым внешним измерением, которое не является неотъемлемой частью самой публикации. – polygenelubricants