簡體   English   中英

按數組中的值排序對象列表;

[英]Sort List of Objects by values from array;

我有一個List<Brand> categories; 有1000多個項目。

對於我有id的列表中的每個項目,為了得到它我使用categories.getId();

我有一個數組int[] sortedIdArr = {4,53,102,403,110,5,6,8,12};

我想對我的categories列表進行排序, sortedIdArr idsortedIdArr中進行sortedIdArr 我該如何實現呢?

private void sortBrandsById(List<Brand> categories) {
    Collections.sort(categories, new Comparator<Brand>() {
        public int compare(Brand o1, Brand o2) {

        }
    });    
}

我可以使用Collections.sort嗎?

通常,您將使用Collections.sort或Java 8中的等效慣用語(如果適用),或者使用排序的Collection (如TreeSet

但是,在這種情況下,您希望遵循由sortedIdArr數組指定的預定義順序。

實現這一目標的一種方法是使用鏈接集合(例如LinkedHashSet )。

然后迭代您的sortedIdArr數組,並在List<Brand>搜索具有給定ID的對象。

如果找到,則將具有給定ID的Brand對象添加到LinkedHashSet ,這將保留插入順序。

請注意,如果找不到ID,則您的Set將不會與陣列完全“匹配”。

自封閉示例,使用Java 8

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;


public class Main {

    // simplified Brand pojo
    static class Brand {
        int id;
        public Brand(int id) {
            this.id = id;
        }
        public int getId() {
            return id;
        }

        // for output clarity
        @Override
        public String toString() {
            return String.format("Brand: %d", id);
        }
    }

    public static void main(String[] args) throws Exception {

        // simplified ID list
        int[] sortedIdArr = {4,53,102};
        // "randomly" ordered Brand list
        final List<Brand> categories = new ArrayList<Brand>() {  
            {
                add(new Brand(1));
                add(new Brand(102));
                add(new Brand(53));
                add(new Brand(4));
                add(new Brand(0));
            }
        };
        // destination: linked set
        Set<Brand> linked = new LinkedHashSet<Brand>();
        // streaming the ID array in order
        Arrays.stream(sortedIdArr)
            .forEach((i) -> {
                // retrieving a Brand with same ID as the current
                // from the "randomly" ordered list
                Optional<Brand> toAdd = categories.stream()
                .filter((b) -> b.getId() == i)
                .findFirst();
                // making sure there's one
                if (toAdd.isPresent()) {
                    // adding to linked set
                    linked.add(toAdd.get());
                }
            }
        );
        System.out.println(linked);
    }

}

產量

[Brand: 4, Brand: 53, Brand: 102]

舊Java版本的命令式成語

for (int i: sortedIdArr) {
    for (Brand b: categories) {
        // assuming no nulls
        if (b.getId() == i) {
            linked.add(b);
            break;
        }
    }
}

是的你可以使用Collections.sort()

要使用id對您的Brand進行排序:

public int compare(Brand o1, Brand o2) {
   return o1.getId().compareTo(o2.getId());
}

要使用id sortedIdArr數組對您的Brand進行排序:

實現Comparator類:

class C implements Comparator<A> {

    int[] idOrder;

    public C(int[] idOrder) {
        super();
        this.idOrder = idOrder;
    }

    @Override
    public int compare(A o1, A o2) {

        Integer indexofO1 = Arrays.binarySearch(idOrder, o1.getId());
        Integer indexofO2 = Arrays.binarySearch(idOrder, o2.getId());
        return indexofO1.compareTo(indexofO2);
    }
}

這里的關鍵思想是反轉過程並使用id的索引而不是id本身進行比較!

要使用它:

Collections.sort(list, new C (idOrder));

測試示例:

int[] idOrder = new int [] {3,1,2};
List<A> list = new ArrayList<>();

list.add(new A(1));
list.add(new A(2));
list.add(new A(3));

System.out.println(list);
//Output : [A [id=1], A [id=2], A [id=3]]

Collections.sort(list, new C(idOrder));

System.out.println(list);
//Output : [A [id=3], A [id=1], A [id=2]]

您可以使用Collections.sort(...)執行此操作,但強烈建議您不要在列表中使用此項目數的情況下使用Comparator方法。

您可以在List<Brand> categories上創建一個循環,並將它們添加到名為tempMap的HashMap<Integer,Brand> 然后使用它按sortedIdArr數組的順序查找它們。 像這樣更改排序方法:

private void sortBrandsById(List<Brand> categories, int [] sortedIdArr) {
    HashMap<Integer,Brand> tempMap = new HashMap<Integer, Brand>(categories.size());
    for (int i = 0; i < categories.size(); i++) {
        tempMap.put(categories.get(i).getId(), categories.get(i));
    }
    categories = new ArrayList<Brand>(sortedIdArr.length);
    for (int i = 0; i < sortedIdArr.length; i++) {
        categories.add(tempMap.get(sortedIdArr[i]));
    }
}

這種排序方式來自訂單O(n)用於創建tempMap + O(n)以重新創建category列表。 雖然, O(1)不能保證HashMap的get / put操作,但java的體面哈希實現非常好且可靠。 因此總復雜度不能比O(n)大得多。 至少它比O(n^2)好得多。 時間復雜度非常重要,我認為你不能找到比O(n)復雜度更接近的方法。

希望這會有所幫助。

您可以使用以下代碼(您需要Apache commons lang jar - 否則您必須遍歷數組才能找到索引)。

private static void sortBrandsById(List<Brand> categories,int[] array) {


            Collections.sort(categories, new Comparator<Brand>() {
                public int compare(Brand o1, Brand o2) {                            

    return ArrayUtils.indexOf(array,o1.getId())-ArrayUtils.indexOf(array,o2.getId());
                }
            });    
        }

如果您能夠將預定義的排序順序放在不在數組中的列表中,則會更容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM