java求对象集合按照指定元素提供的顺序排序算法。

  • 数据源
// 指定顺序
List<String> ids = Stream.of("3", "5", "1", "4", "2").collect(Collectors.toList());

// 待排序数据
List<User> users = Stream.of(new User().setId("1").setName("user1"),
            new User().setId("2").setName("user2"), new User().setId("3").setName("user3"),
            new User().setId("4").setName("user4"), new User().setId("5").setName("user5"),
            new User().setId("6").setName("user6"), new User().setId("7").setName("user7"))
            .collect(Collectors.toList());
class User {
    private String id;

    private String name;
}
  • 目的

求算法,将待排序数据按照指定顺序排序,返回排序后的List<User>(users里面的元素如果也在ids里面那就按ids里面的顺序来,其余的元素放到末尾且按自然顺序排)。

最终效果结构如下:

  • users:
[  
{  
        "id":"3",  
        "name":"user3"  
    },  
{  
        "id":"5",  
        "name":"user5"  
    },  
{  
        "id":"1",  
        "name":"user1"  
    },  
{  
        "id":"4",  
        "name":"user4"  
    },  
{  
        "id":"2",  
        "name":"user2"  
    },  
{  
        "id":"6",  
        "name":"user6"  
    },  
{  
        "id":"7",  
        "name":"user7"  
    }  
]

参考了 java集合指定元素排序:最前,按照提供的顺序排序?求算法,但是还是没有特别好的解决方案,希望能提供个算法学习下~,提前感谢各位大佬。

阅读 10.2k
3 个回答

先按对应的数组下标排,找不到的(indexOf为-1)转为一个大于list容量上限的值
下标一致的按ID自然顺序排


        final Comparator<User> comparingIndex = Comparator.comparing(user -> {
            final int index = ids.indexOf(user.getId());
            return index == -1 ? Long.MAX_VALUE : index;

        });
        final Comparator<User> comparingId = Comparator.comparing(User::getId);
       
       users.stream().sorted(comparingIndex.thenComparing(comparingId)).map(User::getName).forEach(System.out::println);

自定义一个Comparator,需要特殊排序的特殊比较,否则默认比较,就完事了

class UserComparator implements Comparator<User> {

    private final Map<Integer, Integer> preOrdered;

    public UserComparator(List<Integer> ids) {
        preOrdered = new HashMap<>();
        for (int i = 0; i < ids.size(); i++) {
            Integer id = ids.get(i);
            preOrdered.put(id, i);
        }
    }

    @Override
    public int compare(User u1, User u2) {
        Integer o1 = preOrdered.get(u1.getId());
        Integer o2 = preOrdered.get(u2.getId());

        if (o1 != null && o2 != null) {
            return o1 - o2;
        }

        if (o1 != null) {
            return -1;
        }

        if (o2 != null) {
            return 1;
        }

        return u1.getId() - u2.getId();
    }
}

仔细想了下,这样可能符合你的要求

    Person person2 = new Person("2","person2");
    Person person1 = new Person("1","person1");
    Person person4 = new Person("4","person");
    Person person3 = new Person("3","person");
    List<String> ids = Stream.of("2","1").collect(Collectors.toList());
    List<Person> list = Lists.newArrayList(person2,person1,person4,person3);
    list.sort(Comparator.comparing(p->{
                if(ids.contains(p.getId())){
                    return ids.indexOf(p.getId()) - Integer.MAX_VALUE;
                }
                return Integer.parseInt(p.getId());
            },Integer::compareTo));
    System.out.println(list);

[Person(id=2, name=person2), Person(id=1, name=person1), Person(id=3, name=person), Person(id=4, name=person)]

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏