从 LinkedList 中删除重复项,其中嵌套的集合项可以按任意顺序排列

Remove duplicate items from a LinkedList, where the nested collection items can be in any order

我有嵌套链表,其中包含一些 elements.I 想从外部删除重复的内部链表 LinkedList.The 元素的顺序无关紧要。[Cat,Mouse,Dog] 与 [Mouse,猫,狗],我想删除其中的 1 个。 示例:

假设

[[Cat,Mouse,Dog],[Dog,Mouse,Cat],[Dog,Horse,Cat],[Dog,Tiger,Lion]] 

然后我想要这样的输出

[[Cat,Mouse,Dog],[Dog,Horse,Cat],[Dog,Tiger,Lion]]

我试过了。但我想要最优解…… 我的代码如下

for (int iBoardListCnt = 0; this.roomCombinationsMasterList != null && iBoardListCnt < this.roomCombinationsMasterList.size(); iBoardListCnt++) {

        LinkedList<Board> alRoomCombinationList = new LinkedList<>();
        alRoomCombinationList = this.roomCombinationsMasterList.get(iBoardListCnt);
        ArrayList<String> alTemp = new ArrayList();
        for (int icount = 0; icount < alRoomCombinationList.size(); icount++) {
            alTemp.add((alRoomCombinationList.get(icount).getRoomDescription() + alRoomCombinationList.get(icount).getDescription()).toString());
        }
        roomCombinationsMasterList.remove(iBoardListCnt);



        Collections.sort(alTemp, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareToIgnoreCase(s2);
            }
        });

        Iterator<LinkedList<Board>> iterator = roomCombinationsMasterList.iterator();
        while (iterator.hasNext()) {

            ArrayList<String> alTemp1 = new ArrayList<>();
            for (Board data : iterator.next()) {
                alTemp1.add((data.getRoomDescription() + data.getDescription()).toString());

            }
            Collections.sort(alTemp1, new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return s1.compareToIgnoreCase(s2);
                }
            });

            if (alTemp.equals(alTemp1)) {
                iterator.remove();
                continue;
            }

        }

        roomCombinationsMasterList.add(iBoardListCnt, alRoomCombinationList);

    }

在这段代码中,我从 Nested LinkedList 中获取了 Fist 元素。存储在临时 LinkedList 中,我从 main arraylist.Now 中删除了该元素,我将 LinkedList 中的下一个元素存储到第二个临时 LinkedList 中。使用 Comparator 对两个 LinkedList 进行排序,并使用 equals() 方法比较这两个 LinkedList.If 两者是否相同,然后使用 Iterator 删除其中的 1 个。 请给我最佳解决方案。

import java.util.*;

import static me.test.Test.Animal.*;
public class Test {

    public static enum Animal {
        Dog,Tiger,Lion,Horse,Cat,Mouse
    }

    public static void main ( String[] args ) {
        List<Animal> list1 = new LinkedList<>(Arrays.asList(Cat,Mouse,Dog));
        List<Animal> list2 = new LinkedList<>(Arrays.asList(Dog,Mouse,Cat));
        List<Animal> list3 = new LinkedList<>(Arrays.asList(Dog,Horse,Cat));
        List<Animal> list4 = new LinkedList<>(Arrays.asList(Dog,Tiger,Lion));

        List<List<Animal>> list = new LinkedList<>(Arrays.asList(list1, list2, list3, list4));

        Set<List<Animal>> sorted = new LinkedHashSet<>();

        for (List<Animal> animals : list) {
            List<Animal> arList = new ArrayList<>(animals);
            Collections.sort(arList);
            sorted.add(new LinkedList<>(arList));
        }

        for (List<Animal> animals : sorted) {
            System.out.println(animals);
        }
    }
}

算法: 对单个列表进行排序,以便我们可以比较它们。像 [cat, dog] 和 [dog, cat] 这样的列表是相同的,但是等于 return false。现在,只需使用 HashSet。 hashCode() 方法,因为它会在每次添加时遍历各个元素以生成哈希,然后可用于比较列表。我使用了LinkedHashSet,这样就可以恢复原来的顺序。

试试这个,我已经用最短的时间创建了一个优化的解决方案。

public class UniqueLinkedList {

    public static void main(String[] args) {
        List<String> list1 = new LinkedList<>(Arrays.asList("Cat","Mouse","Dog"));
        List<String> list2 = new LinkedList<>(Arrays.asList("Dog","Mouse","Cat"));
        List<String> list3 = new LinkedList<>(Arrays.asList("Dog","Horse","Cat"));
        List<String> list4 = new LinkedList<>(Arrays.asList("Dog","Tiger","Lion"));
        List<List<String>> list = new LinkedList<>(Arrays.asList(list1, list2, list3, list4));
        boolean flag = false;
        boolean matchFlag = true;
        for(int i = 0; i < list.size(); i++){
            for(int j = i+1; j < list.size(); j++){
                if(list.get(i).size() == list.get(j).size()){
                    matchFlag = true;
                    for(String str : list.get(i)){
                        flag = false;
                        for(String string : list.get(j)){
                            if(str.equals(string)){
                                flag = true;
                            }
                        }
                        if(flag == false){
                            matchFlag = false;
                            break;
                        }
                    }
                    if(matchFlag){
                        list.remove(j);
                        j--;
                    }
                }
            }
        }
        System.out.println(list.size());
        for(int i = 0; i < list.size(); i++){
            System.out.println(list.get(i));
        }
    }
}

有多种方法可以从列表中删除重复元素。您要使用的 "optimal" 解决方案将需要使用适当的数据结构,该结构针对 contains 操作进行了优化。在您的情况下,它将是 HashSet

想法是,在遍历原始 collection 的同时,维护已遍历元素的集合并检查当前元素是否已遍历。这种方法会修改您原来的 collection。

    List<List<String>> input = new LinkedList<List<String>>(Arrays.asList(
            Arrays.asList("Cat", "Mouse", "Dog"),
            Arrays.asList("Dog", "Mouse", "Cat"),
            Arrays.asList("Dog", "Horse", "Cat"),
            Arrays.asList("Dog", "Tiger", "Lion")));

    Set<Set<String>> distinctElements = new HashSet<Set<String>>();

    for (Iterator<List<String>> iterator = input.iterator(); iterator.hasNext(); ) {
        List<String> element = iterator.next();
        HashSet<String> elementAsSet = new HashSet<String>(element);
        if (!distinctElements.contains(elementAsSet)) {
            distinctElements.add(elementAsSet);
        } else {
            iterator.remove();
        }
    }

    System.out.println(input);

第二个选项是将您的原始列表列表转换为 LinkedHashSet<LinkedHashSet<String>>LinkedHashSet 同时表现得像 SetList(实际上,它在底层有这两种数据结构)。因此它消除了重复项,同时保留了元素的顺序,正如您所需要的那样。正如您所说,您必须保留 collection 类型,这可能不是您的选择,但它仍然是一个值得考虑的好(和短)选择。

    LinkedHashSet<LinkedHashSet<String>> results = new LinkedHashSet<LinkedHashSet<String>>();
    for (List<String> strings : input) {
        results.add(new LinkedHashSet<>(strings));
    }
    System.out.println(results);

最后 one-liner for Java 8:

LinkedList<LinkedList<String>> results = input.stream().map(LinkedHashSet::new).distinct()
        .map(LinkedList::new).collect(Collectors.toCollection(() -> new LinkedList<LinkedList<String>>()));

如果你不关心返回的类型,它是更短的版本 collection:

List<List<String>> results = input.stream().map(LinkedHashSet::new).distinct()
        .map(LinkedList::new).collect(Collectors.toList());