在Java中如何根据某些条件对无序的自定义对象列表进行排序

mrzz3bfm  于 2023-01-07  发布在  Java
关注(0)|答案(1)|浏览(120)
@Data    
public class DocumentObject {
        public String current;
        public String next;
    
    }
    
    public static void main(String[] args) {
            //Unordered list of objects
            List<DocumentObject> list = Arrays.asList(
                    new DocumentObject("pnp","xyz"),
                    new DocumentObject("z","pnp"),
                    new DocumentObject("123","d"),
                    new DocumentObject("xyz","123"));
            //Expecting ordered list to be returned based on some conditions
            System.out.println(sortingLogic(list));
                    
        }
    
        private static List<DocumentObject> sortingLogic(List<DocumentObject> list) {
            if (list.size() > 0) {
//THIS APPROACH NOT WORKING :(
                  Collections.sort(list, new Comparator<DocumentObject>() {
                      @Override
                      public int compare(DocumentObject o1, DocumentObject o2) {
                          int index1 = list.indexOf(o1.getCurrent());
                          int index2 = list.indexOf(o2.getNext());
    
                          return Integer.compare(index2 , index1);
                      }
                  });
            }
            return list;
        }

//My Expected output
[{"z","pnp"},
{"pnp","xyz"},
{"xyz","123"},
{"123","d"}]

所以逻辑应该像第一个对象必须是{“z”,“pnp”}作为当前对象(“z”)next所在的位置没有对象(“z”),所以它应该是排序后的第一个对象。那么排序后的最后一个对象应该是{“123”,“d”},因为有下一个(“d”),则不存在当前(“d”)的任何对象,因此它是最后一个对象。其余对象根据它们的下一个和当前属性居中排序。
我怎样才能做到这一点?

cwtwac6a

cwtwac6a1#

这个解决方案没有使用比较器来排序,而是将其视为排序问题,并在 O(n) 时间内将列表重新排序为新列表。
首先,它从输入列表构建一个Map<String, DocumentObject>。它将map的所有键作为一个集合(DocumentObject列表中的所有current值),然后从集合中移除所有next元素。这在集合中仅留下将作为根或第一元素的一个元素(因为它没有任何值为next的DocumentObject示例)用图形术语来说,这个元素是唯一一个 in-degree 为0的元素。
最后,从根元素开始,通过按照当前(前一个)元素的next值遍历元素来构建有序列表(使用辅助Map)。

private static List<DocumentObject> sortingLogic(List<DocumentObject> list) {
    Map<String, DocumentObject> map = list.stream()
            .collect(Collectors.toMap(DocumentObject::getCurrent, Function.identity()));

    Set<String> allCurrent = new HashSet<>(map.keySet());
    map.values()
                .forEach(documentObject -> 
                        allCurrent.remove(documentObject.getNext()));

    // The only 'current' value which is not present as next in any of the other entries
    String root = allCurrent.iterator().next();
    List<DocumentObject> orderedDocumentObjects = new ArrayList<>();
    orderedDocumentObjects.add(map.get(root));
        
    for (int i = 1; i < list.size(); i++) {
        String next = orderedDocumentObjects.get(i - 1).getNext();
        orderedDocumentObjects.add(map.get(next));
    }
    return orderedDocumentObjects;
}

相关问题