在ArrayList中对特定对象进行排序,而不更改Java中的其他对

时间:2016-07-14 14:23:15

标签: java arraylist

假设我有一个具有属性Rank和SubRank的对象的ArrayList。它们通过Web服务传递给我,所以我没有处理初始订购。如果没有要使用的subrank,则将其设置为-1。

[Rank: 1, SubRank: -1]
[Rank: 2, SubRank: -1]
[Rank: 3, SubRank: 3]
[Rank: 4, SubRank: 2]
[Rank: 5, SubRank: -1]
[Rank: 6, SubRank: 1]

我需要做的是使用SubRank对任何内容进行排序,只留下剩余的对象,所以列表最终看起来像:

[Rank: 1, SubRank: -1]
[Rank: 2, SubRank: -1]
[Rank: 6, SubRank: 1]
[Rank: 4, SubRank: 2]
[Rank: 5, SubRank: -1]
[Rank: 3, SubRank: 3]

限制:Java 7,没有外部库

2 个答案:

答案 0 :(得分:2)

由于OP已经提到他仅限于Java 7并且没有添加任何库......

制作一个新的List,其中只包含SubRank > -1的项目。然后对List进行排序。然后迭代原始列表,当您到达具有SubRank > -1的项目时,将其替换为已排序列表中的相应项目。

List<Item> sortedItems = new ArrayList<>();
for (Item item : items) {
    if (item.subRank > -1) {
        sortedItems.add(item);
    }
}

Collections.sort(sortedItems,
                 new Comparator<Item>()
                 {
                     @Override
                     public int compare(Item lhs, Item rhs) {
                         return Integer.compare(lhs.SubRank, rhs.SubRank);
                     }
                 });

int sortedIndex = 0;
for (int i; i < items.size(); i++) {
    if (items.get(i).subRank > -1) {
        items.set(i, sortedItems.get(sortedIndex++));
    }
}

答案 1 :(得分:1)

这不是微不足道的。 根据Rank,您可能必须将列表拆分为子列表,然后按子排序对这些子列表进行排序并再次加入。

使用自定义Guava Multimap:

,只需少量疼痛即可完成
public static List<Item> sortBySubRank(List<Item> unsorted) {
  // custom multimap that preserves key order, but sorts values
  // by supplied comparator
  Multimap<Integer, Item> itemsByrank = Multimaps.newMultimap(
    new LinkedHashMap<>(),
    // collection supplier
    () -> new TreeSet<>(
      // custom comparator
      (Comparator<Item>) (o1, o2) -> Integer.compare(o1.subRank, o2.subRank))
  );
  // store in multimap
  unsorted.forEach((i) -> itemsByrank.put(i.rank, i));
  // retrieve sorted values
  return ImmutableList.copyOf(itemsByrank.values());
}

好的,只是为了它的乐趣(和痛苦),这里是没有Guava的Java 7版本基本上做同样的事情:

public static List<Item> sortBySubRankInJava7(List<Item> unsorted) {
  Map<Integer,Set<Item>> map = new LinkedHashMap<>();
  Comparator<Item> comparator=new Comparator<Item>() {
    @Override public int compare(Item o1, Item o2) {
      return Integer.compare(o1.subRank, o2.subRank);
    }
  };
  for (Item item : unsorted) {
    if (map.containsKey(item.rank)) {
      map.get(item.rank).add(item);
    } else {
      TreeSet<Item> set = new TreeSet<>(comparator);
      set.add(item);
      map.put(item.rank, set);
    }
  }
  List<Item> result = new ArrayList<>(unsorted.size());
  for (Set<Item> items : map.values()) {
    result.addAll(items);
  }
  return result;
}