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

阅读 732
评论
    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);
      • 3.9k

      自定义一个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)]

          撰写回答

          登录后参与交流、获取后续更新提醒

          相似问题
          推荐文章