Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
集合和列表接口的Java组合_Java_List_Collections_Set - Fatal编程技术网

集合和列表接口的Java组合

集合和列表接口的Java组合,java,list,collections,set,Java,List,Collections,Set,我有一个数据结构,目前正在使用ArrayList。我意识到,在这种结构中,我不希望出现任何副本。我的第一个想法是使用某种形式的集合,但是顺序也很重要。在谷歌搜索了一段时间收集文档后,我找到了LinkedHashSet,几乎可以胜任这项工作。不幸的是,保留顺序的一个主要原因是,我使用ArrayList的get(int index)方法进行随机访问,我看不到任何解决方法 更简洁地说,我需要一个能够保持顺序并允许随机访问的集合。到目前为止,我所研究的所有类都没有提供这种功能。有谁知道有一个班级提供这种

我有一个数据结构,目前正在使用
ArrayList
。我意识到,在这种结构中,我不希望出现任何副本。我的第一个想法是使用某种形式的集合,但是顺序也很重要。在谷歌搜索了一段时间收集文档后,我找到了
LinkedHashSet
,几乎可以胜任这项工作。不幸的是,保留顺序的一个主要原因是,我使用ArrayList的
get(int index)
方法进行随机访问,我看不到任何解决方法

更简洁地说,我需要一个能够保持顺序并允许随机访问的集合。到目前为止,我所研究的所有类都没有提供这种功能。有谁知道有一个班级提供这种服务,还是我必须自己制作?如果是后一种情况,那么在创建人们意识到的结构时是否存在任何陷阱

(或者,用一种快速简便的方法检查和删除ArrayList或类似结构中的重复项就足够了)

编辑:为清楚起见,重要的是元素添加到列表中的顺序,而不是它们之间的比较方式

List<Foo> uniqueList = SetUniqueList.decorate(new ArrayList<Foo>());
List uniqueList=SetUniqueList.decoration(new ArrayList());

(不幸的是,commons collections仍然不支持泛型,因此您必须在此处禁止显示警告)

如何创建AbstractList的子类,该子类保留ArrayList作为其备份存储区,重写大多数方法以将其委托给备份存储区,并重写
add()
以拒绝重复项

class NoDupesList<E> extends AbstractList<E> {
    private final List<E> backing;

    NoDupesList() {
        backing = new ArrayList<E>();
    }

    public E get(int index) {
        return backing.get(index);
    }

    // ...

    public boolean contains(Object o) {
        return backing.contains(o);
    }

    public boolean add(E e) {
        if (contains(e))
            throw new IllegalArgumentException("duplicates disallowed: " + e):

        return backing.add(e);
    }
 }
类NoDupesList扩展了AbstractList{
私人最终名单;
NoDupesList(){
backing=newarraylist();
}
公共E-get(int索引){
返回backing.get(索引);
}
// ...
公共布尔包含(对象o){
返回支持。包含(o);
}
公共布尔加法(E){
如果(包含(e))
抛出新的IllegalArgumentException(“不允许重复:+e”):
加上(e);
}
}

您可以同时使用ArrayList和HashMap:

import java.util.*;

class AS<T>{

    private HashMap<T, Integer> m = new HashMap<T, Integer>();
    private ArrayList<T> a = new ArrayList<T>();

    public void add(T object){
        if (!m.containsKey(object)){
            m.put(object, a.size());
            a.add(object);
        }
    }
    public void remove(T object){
        Integer i = m.get(object);
        if (i!=null){
            a.remove(i.intValue());
            m.remove(object);
        }
    }
    public void remove(int index){
        m.remove(a.get(index));
        a.remove(index);
    }
    public T get(int index){
        return a.get(index);
    }

    public String toString(){return a.toString();}
}
import java.util.*;
类别为{
私有HashMap m=新HashMap();
私有ArrayList a=新ArrayList();
公共无效添加(T对象){
如果(!m.containsKey(对象)){
m、 放置(对象,a.size());
a、 添加(对象);
}
}
公共无效删除(T对象){
整数i=m.get(对象);
如果(i!=null){
a、 删除(i.intValue());
m、 移走(物体);
}
}
公共无效删除(整型索引){
m、 删除(a.get(index));
a、 删除(索引);
}
公共T获取(整数索引){
返回a.get(索引);
}
公共字符串toString(){返回a.toString();}
}

我只想扩展
ArrayList

public class SetList<E> extends ArrayList<E> {

    @Override
    public boolean add(E e) {
        return contains(e) ? false : super.add(e);
    }

    @Override
    public void add(int index, E e) {
        if (!contains(e)) {
            super.add(index, e);
        }
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return addAll(size(), c);
    }

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

}
公共类集合列表扩展了ArrayList{
@凌驾
公共布尔加法(E){
返回包含(e)?否:超级添加(e);
}
@凌驾
公共无效添加(整数索引,E){
如果(!包含(e)){
super.add(索引e);
}
}
@凌驾

公共布尔加法(CollectionUse a TreeMap。您可以在类型和整数之间使用双向映射。这样,您可以确保唯一性,并进行快速查找。但新的整数键需要全局计数器。@Maurício:这不起作用。映射允许重复值。限制仅限于键。集合不会引发异常。它们替换元素。如果您使用此方法,并且内存效率不是最重要的,那么您可以同时保留
ArrayList
HashSet
作为后备存储。如果使用此方法,则只有删除操作--
remove(int)
remove(Object)
等将为O(n).Duh:P好的,我很胖,我可以扩展ArrayList和ovveride add()来拒绝重复项,我甚至不需要支持列表。这个答案向我指出了这一点。如果你正在使用,扩展可能有助于最小化样板文件。这
add()
方法不符合方法的约定。它不应该在重复时抛出异常,而只返回
false
。请注意,总共有4个
add
方法需要实现。如果集合实现了
列表
接口,会更好如果客户端将此类型用作列表,那么y插入重复项将破坏消除重复项的集合约定?这将是非常不充分的:ArrayList.contains()进行顺序搜索;也就是说,如果您有一百万个元素,并且需要再添加一个元素,那么您必须进行一百万次比较。它使用一个内部集合来进行存在性检查,因此从速度上来说,这是一个足够好的解决方案,尽管它会花费一些额外的内存。