那里有没有重复的List实现吗?

时间:2008-11-06 13:25:41

标签: java list collections duplicates

我知道SortedSet,但就我而言,我需要一些实现List而不是Set的东西。那么在API或其他地方是否有实现?

实现自己应该不难,但我想为什么不先问问这里的人呢?

11 个答案:

答案 0 :(得分:84)

标准库中没有Java集合来执行此操作。 LinkedHashSet<E>保留了与List类似的排序,因此,如果您想将List用作List,那么当您想要将其用作commons-collections4时,您将获得语义你想要的。

或者,Commons Collections(或通用版本的List)有一个{{1}}可以执行您想要的操作:SetUniqueList / SetUniqueList<E>

答案 1 :(得分:11)

这是我做的,它的工作原理。

假设我有ArrayList处理我做的第一件事就是创建了一个新的LinkedHashMap

LinkedHashSet<E> hashSet = new LinkedHashSet<E>()

然后我尝试将我的新元素添加到LinkedHashSet。 add方法不会更改LinkedHasSet,如果新元素是重复的,则返回false。所以这成为我在添加ArrayList之前可以测试的条件。

if (hashSet.add(E)) arrayList.add(E);

这是一种简单而优雅的方法,可以防止将重复项添加到数组列表中。如果需要,可以在扩展ArrayList的类中封装并覆盖add方法。只需记住通过循环遍历元素并调用add方法来处理addAll

答案 2 :(得分:10)

所以这就是我最终做的。我希望这有助于其他人。

class NoDuplicatesList<E> extends LinkedList<E> {
    @Override
    public boolean add(E e) {
        if (this.contains(e)) {
            return false;
        }
        else {
            return super.add(e);
        }
    }

    @Override
    public boolean addAll(Collection<? extends E> collection) {
        Collection<E> copy = new LinkedList<E>(collection);
        copy.removeAll(this);
        return super.addAll(copy);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> collection) {
        Collection<E> copy = new LinkedList<E>(collection);
        copy.removeAll(this);
        return super.addAll(index, copy);
    }

    @Override
    public void add(int index, E element) {
        if (this.contains(element)) {
            return;
        }
        else {
            super.add(index, element);
        }
    }
}   

答案 3 :(得分:4)

为什么不用列表封装一个集合,如:

new ArrayList( new LinkedHashSet() )

这使得其他实现成为真正的集合主人; - )

答案 4 :(得分:4)

你应该认真考虑dhiller的回答:

  1. 不要担心将对象添加到无重复的List中,而是将它们添加到Set(任何实现)中,这本质上会过滤掉重复项。
  2. 当您需要调用需要List的方法时,请将其包装在new ArrayList(set)(或new LinkedList(set),无论如何)中。
  3. 我认为您使用NoDuplicatesList发布的解决方案存在一些问题,主要是使用contains()方法,而且您的类无法检查传递给{{1}的集合中的重复项方法。

答案 5 :(得分:3)

我需要这样的东西,所以我去了commons集合并使用了SetUniqueList,但是当我运行一些性能测试时,我发现它似乎没有优化,如果我想使用一个Set并获得一个使用Set.toArray()方法的数组,SetUniqueTest需要20:1的时间来填充然后遍历100,000个字符串,与其他实现相比,这是一个很大的差异,所以如果你担心性能,我建议你使用设置并获取一个数组而不是使用SetUniqueList,除非你真的需要SetUniqueList的逻辑,那么你需要检查其他解决方案......

测试代码主要方法:

public static void main(String [] args){

SetUniqueList pq = SetUniqueList.decorate(new ArrayList());
Set s = new TreeSet();

long t1 = 0L;
long t2 = 0L;
String t;


t1 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
    pq.add("a" + Math.random());
}
while (!pq.isEmpty()) {
    t = (String) pq.remove(0);
}
t1 = System.nanoTime() - t1;

t2 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
    s.add("a" + Math.random());
}

s.clear();
String[] d = (String[]) s.toArray(new String[0]);
s.clear();
for (int i = 0; i < d.length; i++) {
    t = d[i];

}
t2 = System.nanoTime() - t2;

System.out.println((double)t1/1000/1000/1000); //seconds
System.out.println((double)t2/1000/1000/1000); //seconds
System.out.println(((double) t1) / t2);        //comparing results

}

此致 穆罕默德·莱姆 http://abusleem.net/blog

答案 6 :(得分:1)

注意:它不会考虑 subList 实现。

class IODetection {
    class func monitorUSBEvent(VendorID: Int, ProductID: Int) {


        var portIterator: io_iterator_t = 0
        var kr: kern_return_t = KERN_FAILURE
        let matchingDict = IOServiceMatching(kIOUSBDeviceClassName)

        // Add the VENDOR and PRODUCT IDs to the matching dictionary.
        let vendorIDString = kUSBVendorID as CFStringRef!
        let productIDString = kUSBProductID as CFStringRef!
        CFDictionarySetValue(matchingDict, unsafeAddressOf(vendorIDString), unsafeAddressOf(VendorID))
        CFDictionarySetValue(matchingDict, unsafeAddressOf(productIDString), unsafeAddressOf(ProductID))

        // To set up asynchronous notifications, create a notification port and add its run loop event source to the program’s run loop
        let gNotifyPort: IONotificationPortRef = IONotificationPortCreate(kIOMasterPortDefault)
        let runLoopSource: Unmanaged<CFRunLoopSource>! = IONotificationPortGetRunLoopSource(gNotifyPort)
        let gRunLoop: CFRunLoop! = CFRunLoopGetCurrent()

        CFRunLoopAddSource(gRunLoop, runLoopSource.takeRetainedValue(), kCFRunLoopDefaultMode)

        // MARK: - USB in Notification
        let observer = UnsafeMutablePointer<Void>(unsafeAddressOf(self))
        kr = IOServiceAddMatchingNotification(gNotifyPort,
                                              kIOMatchedNotification,
                                              matchingDict,
                                              deviceAdded,
                                              observer,
                                              &portIterator)
        deviceAdded(nil, iterator: portIterator)


        // MARK: - USB remove Notification
        kr = IOServiceAddMatchingNotification(gNotifyPort,
                                              kIOTerminatedNotification,
                                              matchingDict,
                                              deviceRemoved,
                                              observer,
                                              &portIterator)
        deviceRemoved(nil, iterator: portIterator)

    }
}

func deviceAdded(refCon: UnsafeMutablePointer<Void>, iterator: io_iterator_t) -> Void {
    var kr: kern_return_t = KERN_FAILURE

    while case let usbDevice = IOIteratorNext(iterator) where usbDevice != 0 {
        let deviceNameAsCFString = UnsafeMutablePointer<io_name_t>.alloc(1)
        defer {deviceNameAsCFString.dealloc(1)}
        kr = IORegistryEntryGetName(usbDevice, UnsafeMutablePointer(deviceNameAsCFString))
        if kr != KERN_SUCCESS {
            deviceNameAsCFString.memory.0 = 0
        }
        let deviceName = String.fromCString(UnsafePointer(deviceNameAsCFString))
        print("Device Added: \(deviceName!)")

        // Do something if I get the specific device
        if deviceName == "YOUR DEVICE" {
            /// Your Action HERE
        }

        IOObjectRelease(usbDevice)
    }
}

答案 7 :(得分:0)

documentation for collection interfaces说:

  

设置 - 不能包含重复元素的集合   列表 - 有序集合(有时称为序列)。列表可以包含重复的元素。

因此,如果您不想要重复,则可能不应该使用列表。

答案 8 :(得分:-1)

在我的头顶,列表允许重复。在调用继承的方法之前,您可以快速实现UniqueArrayList并覆盖所有add / insert函数以检查contains()。对于个人使用,您只能实现您使用的add方法,并覆盖其他方法以引发异常,以防将来的程序员尝试以不同的方式使用该列表。

答案 9 :(得分:-1)

add方法中,为什么不使用HashSet.add()检查重复项而不是HashSet.consist()。 如果没有重复,HashSet.add()将返回true,否则会返回false

答案 10 :(得分:-3)

我只是在我自己的小库中创建了我自己的UniqueList:

package com.bprog.collections;//my own little set of useful utilities and classes

import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Jonathan
*/
public class UniqueList {

private HashSet masterSet = new HashSet();
private ArrayList growableUniques;
private Object[] returnable;

public UniqueList() {
    growableUniques = new ArrayList();
}

public UniqueList(int size) {
    growableUniques = new ArrayList(size);
}

public void add(Object thing) {
    if (!masterSet.contains(thing)) {
        masterSet.add(thing);
        growableUniques.add(thing);
    }
}

/**
 * Casts to an ArrayList of unique values
 * @return 
 */
public List getList(){
    return growableUniques;
}

public Object get(int index) {
    return growableUniques.get(index);
}

public Object[] toObjectArray() {
    int size = growableUniques.size();
    returnable = new Object[size];
    for (int i = 0; i < size; i++) {
        returnable[i] = growableUniques.get(i);
    }
    return returnable;
    }
}

我有一个看起来像这样的TestCollections类:

package com.bprog.collections;
import com.bprog.out.Out;
/**
*
* @author Jonathan
*/
public class TestCollections {
    public static void main(String[] args){
        UniqueList ul = new UniqueList();
        ul.add("Test");
        ul.add("Test");
        ul.add("Not a copy");
        ul.add("Test"); 
        //should only contain two things
        Object[] content = ul.toObjectArray();
        Out.pl("Array Content",content);
    }
}

工作正常。它所做的只是它添加到一个集合,如果它还没有它,并且有一个可返回的Arraylist,以及一个对象数组。