2014-06-17 37 views
4

我有一個扁平的多對象(列表)對象,我想將其轉換爲列表中'key'屬性/字段(例如名稱以下爲)在所有參賽作品中都是獨一無二的。優雅的解決方案,用於過濾列表對於給定的對象屬性是唯一的

在多個條目具有相同的密鑰()與最大的creationDate字段中的條目應挑選的情況下。

實施例:

List<Object> myList = 
[ 
    {name="abc", age=23, creationDate = 1234L}, 
    {name="abc", age=12, creationDate = 2345L}, 
    {name="ddd", age=99, creationDate = 9999L} 
] 

應轉換爲:

List<Object> = 
[ 
    {name="abc", age=12, creationDate = 2345L}, 
    {name="ddd", age=99, creationDate = 9999L} 
] 

是否有在Java中來解決這個一種優雅的方式(可能使用番石榴庫?)?我意識到我可以試着用這個名稱爲的HashMap作爲查找所有唯一條目的關鍵,但我感覺有更好的方法來解決這個問題。

謝謝!

回答

3

如果你有可能使用Java 8,我會推薦Streams作爲其他答案已經告訴。 如果沒有,你可以去這樣的事情。

首先您按照creationDate對List desending進行排序。然後你創建一個TreeSet女巫對待所有具有相同名字的人。因此只有第一個(最高)的creationDate會被添加,並且會被忽略。

List<Person> persons = new ArrayList<>(); 
persons.add(new Person("abc", 23, 1234L)); 
persons.add(new Person("abc", 12, 2345L)); 
persons.add(new Person("def", 99, 9999L)); 

Collections.sort(persons, new Comparator<Person>() { 
    public int compare(Person o1, Person o2) { 
      return (int) (o2.creationDate - o1.creationDate); 
    } 
}); 

Set<Person> personsHashed = new TreeSet<>(new Comparator<Person>() { 
    public int compare(Person o1, Person o2) { 
     return o2.name.compareTo(o1.name); 
    } 
}); 
personsHashed.addAll(persons); 
+0

太棒了!謝謝!我沒有Java 8可用,但這個解決方案非常簡潔/可讀。我可能會提出一個關於TreeSet副作用的評論,只是選擇了第一個值(我不知道)。 –

1

在Java 8中,您可以使用新的Streaming API獲取集合通過過濾器對其進行流式處理,然後生成結果。這應該能夠做你正在尋找的東西。

或者,您已經考慮將它們放入HashMap中的想法看起來很簡單,並且會給出您需要的行爲。我不會嘗試過想這:)

2

這是否被認爲是優雅而主觀的,但這裏有雲:

static List<Person> byName(Collection<Person> persons) { 
    Map<String, Person> personsByName = persons.stream().collect(
     Collectors.groupingBy(Person::getName, 
      Collectors.collectingAndThen(
       Collectors.maxBy(
        Comparator.comparingLong(Person::getCreationDate)), 
       p -> p.get()))); 
    return new ArrayList<Person>(personsByName.values()); 
} 

可以使用靜態導入的方法使其稍微更具可讀性收集器和比較器,如:

import static java.util.stream.Collectors.collectingAndThen; 
import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.maxBy; 
import static java.util.Comparator.comparingLong; 

然後代碼可以稍微縮短爲:

static List<Person> byName(Collection<Person> persons) { 
    Map<String, Person> personsByName = 
     persons.stream().collect(
      groupingBy(Person::getName, collectingAndThen(
       maxBy(comparingLong(Person::getCreationDate)), 
       p -> p.get()))); 
    return new ArrayList<Person>(personsByName.values()); 
} 
相關問題