GVKun编程网logo

比较Java中的两个Collection(java比较两个集合用什么方法)

6

本文将带您了解关于比较Java中的两个Collection的新内容,同时我们还将为您解释java比较两个集合用什么方法的相关知识,另外,我们还将为您提供关于.Java中Collection的使用、do

本文将带您了解关于比较Java中的两个Collection的新内容,同时我们还将为您解释java比较两个集合用什么方法的相关知识,另外,我们还将为您提供关于.Java中Collection的使用、dom – Meteor:当我插入CollectionB时,CollectionA中的元素重新渲染、Java Collection Framework -Collection接口的具体详解、Java Collection 【对抗遗忘系列】 - 对Collection不断的梳理的实用信息。

本文目录一览:

比较Java中的两个Collection(java比较两个集合用什么方法)

比较Java中的两个Collection(java比较两个集合用什么方法)

我在Java类中有两个Collections。第一个集合包含先前的数据,第二个集合包含先前集合的更新数据。

我想比较这两个集合,但是我不确定有效实现此目的的最佳方法。两个集合都包含相同数量的项目。

然后,基于每个集合中的carType相同,我要执行carType方法。

任何帮助表示赞赏

答案1

小编典典

很难帮助,因为你没有告诉我们 如何 你想比较(大小相等)的集合。一些想法,希望能适合:

比较两个集合,如果它们包含相同顺序的相同对象

Iterator targetIt = target.iterator();for (Object obj:source)  if (!obj.equals(targetIt.next()))    // compare result -> false

比较两个集合(如果它们以任意顺序包含相同的对象)

for (Object obj:source)  if (target.contains(obj))    // compare result -> false

在其他集合中查找已更改的元素

Iterator targetIt = target.iterator();for (Object obj:source)  if (!obj.equals(targetIt.next())    // Element has changed

根据您的评论,此算法可以做到。它收集所有已更新的汽车。如果方法结果为空列表,则两个集合均包含相同顺序的相等条目。该算法 依赖
于正确实施equals()Car类型!

public List<Car> findUpdatedCars(Collection<Car> oldCars, Collection<Car> newCars)  List<Car> updatedCars = new ArrayList<Car>();  Iterator oldIt = oldCars.iterator();  for (Car newCar:newCars) {    if (!newCar.equals(oldIt.next()) {      updatedCars.add(newCar);    }  }  return updatedCars;}

.Java中Collection的使用

.Java中Collection的使用

相信用过vb的朋友都知道,vb中有个collection集合类型,用于保存相关元素值到集合,其实质就是一个列表.Java中对Collection进一步抽象封装,使之成为一个集合的接口,根据此接口,抽象出可重复的List,arrayList列表,也可抽象出不可重复的Set,HashSet列表.下面是使用Collection的范例.希望对大家有帮助.

import java.util.*;
public class test {

 
 public static void main(String[] args) {
  
  // 没有重复的集合列表***********begin**********
  Collection mycoll=new HashSet();
  mycoll.add("China");
  mycoll.add("Canada");
  mycoll.add("Japan");
  mycoll.add("Italy");
  mycoll.add("China");
  System.out.println("size="+mycoll.size());
  for(Iterator it=mycoll.iterator();it.hasNext();)
  {
   System.out.println(it.next());
  }
       //   没有重复的集合列表***********end**********
  System.out.println("******************************");
  //  有重复的集合列表***********begin**********
  Collection lstcoll=new ArrayList();
  lstcoll.add("China");
  lstcoll.add("Canada");
  lstcoll.add("Japan");
  lstcoll.add("Italy");
  lstcoll.add("China");
  System.out.println("size="+lstcoll.size());
  for(Iterator itLst=lstcoll.iterator();itLst.hasNext();)
  {
   System.out.println(itLst.next());
  }
       //    有重复的集合列表***********end********** 
  
 }   

}

dom – Meteor:当我插入CollectionB时,CollectionA中的元素重新渲染

dom – Meteor:当我插入CollectionB时,CollectionA中的元素重新渲染

我试图在用户发布的评论的被动{{#each}}中淡入新元素.

我在https://gist.github.com/3119147的一个非常简单的注释部分有一个代码示例(textarea和新的注释插入代码不包括在内,但它是非常样板的.).包含CSS的片段,我给.comment.fresh {opacity:0;然后在我的脚本中,我有:

Template.individual_comment.postedago_str = function() {
  var id = this._id;
  Meteor.defer(function() {
    $('#commentid_'+id+'.fresh').animate({'opacity':'1'},function() {
      $(this).removeClass('fresh');
    });
  });
  return new Date(this.time).toString();
};

这似乎是执行动画的一个可怕的地方.我的想法是,每次渲染一个新的注释时,它都需要调用我所有的Template.individual_comment.*函数,这就是为什么我的动画会推迟其中一个.但是,每次插入不同的集合(Likes)时,Meteor都会调用Template.individual_comment.postedago_str().这意味着我单击Like按钮,我的整个注释列表闪烁白色并淡入(非常烦人!).

我阅读了Meteor文档并尝试弄清楚如何更好地切片我的模板以便只更新块,并且我在任何地方添加了id =“”属性,这似乎是合理的..仍然是这个bug.有谁知道发生了什么?

TIA!

解决方法

作为一种解决方法,您可以在单个注释上围绕新类封装{{if}}块,这将检查注释的创建时间,并且如果注释实际上是最近的,则仅在第一个位置添加新类.就像是:

<divid="commentid_{{_id}}">

然后定义isActuallyFresh函数:

Template.individual_comment.isActuallyFresh = function() {
  if ((new Date().getTime() - this.time) < 300000) // less than 5 minutes old
     return true;
  else
     return false;

Java Collection Framework -Collection接口的具体详解

Java Collection Framework -Collection接口的具体详解


一、要点

  • collection 接口

  • Collection 接口的默认实现:AbstractCollection

  • Optional operations(可选方法)


二、Collection 接口

1、JDK 对 Collection 接口的描述

  Collection 接口是 Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection(List,Queue) 允许有重复的元素,而另一些(Set)则不允许。一些 collection (List,Queue)是有序的,而另一些(Set)则是无序的。JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List)实现,这些子接口继承自Collection 接口。此接口通常用来传递 collection(多态),并在需要最大普遍性的地方操作这些 collection

立即学习“Java免费学习笔记(深入)”;

  所有通用的 Collection 实现类(通常通过它的一个子接口间接实现 Collection)应该提供 两个“标准”构造方法: 一个是 void(无参数)构造方法,用于创建空 collection;另一个是带有 Collection 类型单参数的构造方法,用于创建一个具有与其参数相同元素新的 collection。实际上,后者允许用户复制任何 collection,以生成所需实现类型的一个等效 collection。尽管无法强制执行此约定(因为接口不能包含构造方法),但是 Java 平台库中所有通用的 Collection 实现都遵从它。

  此接口中包含的“破坏性”方法,是指可修改其所操作的 collection 的那些方法,如果此 collection 不支持该操作,则指定这些方法抛出 UnsupportedOperationException(可选操作)。

  Collections Framework 接口中的很多方法是根据 equals 方法定义的。

  Collections Framework 中的各个容器均是非线程安全的。  
  
  Collection 接口的定义如下:

public interface Collection<E> extends Iterable<E> { ... }
登录后复制

            Java Collection Framework.png-155.6kB


2、行为

   java.util.Collection 接口是描述 Set 和 List 集合类型的根接口,下面给出了Collection 的所有行为(不包括从Object 继承而来的方法),因此它们也刻画了 Set 或 List 执行的所有行为(List 还有额外的功能)。Collection 的行为分类和详细列表如下 :

     Collection行为分类.png-29.5kB
      
                        表1. Collection 的操作

FunctionIntroductionNote
boolean add(T)将指定元素添加到集合中,若未将该元素添加到容器,返回 false可选操作
boolean addAll(Collection)添加参数中的所有元素,只要添加进任意元素则返回 true可选操作
Iterator iterator( )遍历容器中的元素(统一的访问、遍历方法,对外屏蔽了不同容器的差异性,迭代器模式)依赖于具体实现
boolean remove(Object)向容器移除指定元素,若移除动作发生,则返回 true(若有重复对象,一次只删除其中一个可选操作
boolean removeAll(Collection)向容器移除参数中所有元素,若有移除动作发生,则返回 true可选操作
Boolean retainAll(Collection)只保存参数中的元素,只要Collection 发生改变,则返回 true可选操作
void clear()移除容器中所有元素可选操作
boolean contains(T)若容器持有该元素,返回 true依赖于equals()
Boolean containsAll(Collection)若容器持有参数中的所有元素,返回 true依赖于equals()
object[] toArray()返回一个包含该容器所有元素的 Object 型数组Array与Collection之间的桥梁,在 AbstractCollection 中提供默认实现,子类可以对它重写
T[] toArray(T[] a)返回一个包含该容器所有元素的 Object 型数组,且返回结果的运行时类型与参数数组 a 相同,而不单纯是objectArray与Collection之间的桥梁,在 AbstractCollection 中提供默认实现,子类可以对它重写
int size()返回容器中元素数目依赖于具体实现
boolean isEmpty()容器为空,则返回 true依赖于size()

   注意到,其中不包含随机访问所选择的元素 get() 方法,因为 Collection 包含 Set,而 Set 是自己维护顺序的。因此,若想访问、遍历 Collection 中的元素,则必须使用迭代器; 另外,这些方法的默认实现(AbstractCollection)均直接或间接使用了迭代器。


三、Collection 接口的默认实现:AbstractCollection

1、JDK 对 AbstractCollection 抽象类的描述

   此抽象类提供 Collection 接口的骨干实现,以最大限度地减少实现此接口所需的工作。 要实现一个不可修改的 collection,编程人员只需扩展此类,并提供 iterator 和 size 方法的实现。(iterator 方法返回的迭代器必须实现 hasNext 和 next。); 要实现可修改的 collection,编程人员必须另外重写此类的 add 方法(否则,会抛出 UnsupportedOperationException),iterator 方法返回的迭代器还必须另外实现其 remove 方法(AbstractCollection 的移除方法间接调用迭代器的移除方法)。按照 Collection 接口规范中的建议,编程人员通常应提供一个 void (无参数)和 Collection 构造方法。

    Iterator.png-6.6kB

  AbstractCollection 抽象类定义如下:

public abstract class AbstractCollection<E> implements Collection<E> { ... }
登录后复制

2、行为(对上述 Collection 接口中方法的实现情况)

  下面给出了抽象类 AbstractCollection 对 Collection 接口的实现情况:

    public boolean add(E e) {   
     throw new UnsupportedOperationException();
    }  
     public boolean addAll(Collection<? extends E> c) {  
      boolean modified = false;
    Iterator<? extends E> e = c.iterator();   
     while (e.hasNext()) {     
       if (add(e.next()))                
         // 调用了上面定义的 add 方法
        modified = true;
    }    return modified;
    }    public abstract Iterator<E> iterator();               
    //未提供具体实现,将实现延迟到具体容器


    public boolean remove(Object o) {
    Iterator<E> e = iterator();    
    if (o==null) {       
     while (e.hasNext()) {       
      if (e.next()==null) {
            e.remove();                 
            //内部使用了迭代器的 remove 方法,故具体容器的迭代器实现密切相关
            return true;
        }
        }
    } else {        
    while (e.hasNext()) {      
      if (o.equals(e.next())) {
            e.remove();           
             return true;
        }
        }
    }    return false;
    }    public boolean removeAll(Collection<?> c) {  
      boolean modified = false;
    Iterator<?> e = iterator();    
    while (e.hasNext()) {     
       if (c.contains(e.next())) {
        e.remove();                       
        //内部使用了迭代器的 remove 方法,故具体容器的迭代器实现密切相关
        modified = true;
        }
    }    return modified;
    }    public boolean retainAll(Collection<?> c) {    
    boolean modified = false;
    Iterator<E> e = iterator();   
     while (e.hasNext()) {        
    if (!c.contains(e.next())) {
        e.remove();                       
        //内部使用了迭代器的 remove 方法,故具体容器的迭代器实现密切相关
        modified = true;
        }
    }    return modified;
    }    public void clear() {
    Iterator<E> e = iterator();    
    while (e.hasNext()) {
        e.next();
        e.remove();                       
        //内部使用了迭代器的 remove 方法,故具体容器的迭代器实现密切相关
    }
    }    public boolean contains(Object o) {
    Iterator<E> e = iterator();    
    if (o==null) {        
    while (e.hasNext())        
    if (e.next()==null)            
    return true;
    } else {        while (e.hasNext())        
    if (o.equals(e.next()))                 
    //内部调用了的 equals方法,故与 equals 方法实现密切相关
            return true;
    }    return false;
    }    public boolean containsAll(Collection<?> c) {
    Iterator<?> e = c.iterator();    
    while (e.hasNext())        
    if (!contains(e.next()))                
    //内部调用了的 contains 方法,故与 contains 方法实现密切相关
        return false;    return true;
    }    //此处省略两个 toArray 方法的实现


    public abstract int size();                   
    //未提供具体实现,将实现延迟到具体容器


    public boolean isEmpty() {    return size() == 0;                      
    //内部调用了的 size 方法,故与 size 方法实现密切相关
    }
登录后复制

   对以上实现进行总结 :

  • 】:add, addAll 两个方法的实现是可选的,此处均默认 UnsupportedOperationException ;

  • 】:iterator 未提供具体实现,将实现延迟到具体容器,其对外屏蔽了不同容器的差异性,以统一的方式对容器访问、遍历 ;

  • 】:remove(Object),removeAll(Collection) ,retainAll(Collection) 和 clear() 四个方法的实现均直接调用了具体容器的迭代器(由 iterator() 方法返回)的 remove 方法 ;

  • 】:contains(Object o) 和 containsAll(Collection c) 两个方法的实现均直接或间接调用了元素的 equals 方法 ;

  • 基本方法】:size 方法实现与具体容器相关, isEmpty 方法的实现均直接调用了 size 方法 ;

  • 容器与数组转换】:分别提供与泛型 toArray 方法 和 原生 toArray 方法;


   从源代码中我们可以知道,几乎所有方法的实现都与迭代器相关,并且有以下特点:

  • 执行各种不同的添加和移除方法在 Collection 接口中都是可选操作,因为他们会改变容器的结构;

  • Collection 接口中的读取方法都不是可选操作 ;


四、Optional operations(可选操作)

1、简述

   执行各种不同的添加和移除方法在 Collection 接口中都是可选操作, 这意味着实现类并不需要为这些方法提供功能定义。

   这是一种很不寻常的接口定义方式。正如你所看到的那样,接口是面向对象设计中的契约,它声明 “无论你选择如何实现该接口,我保证你可以向该接口发送这些消息。”但可选操作违反这个非常基本的原则,它声明调用某些方法将不会执行有意义的行为,相反,他们会抛出异常。

   为什么会将方法定义为可选呢? 因为这样做可以防止在设计中出现接口爆炸的情形。容器类库中的设计看起来总是为了描述每个主题的变体,而最终患上了令人困惑的接口过剩症。甚至这么做仍不能捕获接口的各种特例,因为总是有人会发明新的接口。“未获支持的操作” 这种方式可以实现 Java 容器类库的一个重要目标:容器应易学易用。未获支持的操作是一种特例,可以延迟到需要时实现。但是,为了让这种方式能够工作:

  1. UnsupportedOperationException 必须是一种罕见事件。即,对于大多数类而言,所有操作都应该可以工作,只有在特例(例如,通过Arrays.asList()所得到的容器)中才会有未获支持的操作。在 Java 容器类库中确实如此,因为你在 99% 的时间里使用的容器类,如 ArrayList、LinkedList、HashSet 和 HashMap,以及其他的具体实现,都支持所有操作。这种设计留下了一个“后门”,如果你想创建新的 Collection, 但是没有为 Collection 接口中的所有方法都提供有意义的定义,那么它仍旧适合现有类库。

  2. 如果一个操作是未获支持的,那么在实现接口的时候可能就会导致 UnsupportedOperationException 异常,而不是将产品程序交给客户后才出现此异常,这种情况是有道理的。毕竟,他表示编程上有错误:使用了不正确的接口实现。

     值得注意的是,未获支持操作只有在运行时才能探测到,因此他们表示动态类型检查。


2、示例

   最常见的未获支持的操作,都来源于背后由固定尺寸的数据结构支持的容器。当你用 Arrays.asList() 将数组转换为 List 时,就会得到这样的容器。此外,你还可以通过使用 Collection 类中“不可修改”的方法,选择创建任何会抛出会抛出 UnsupportedOperationException 的容器。

   请看下面的例子:

public class Unsupported {
    static void test(String msg, List<String> list) {
        System.out.println("--- " + msg + " ---");
        Collection<String> c = list;
        Collection<String> subList = list.subList(1, 8);        
        // Copy of the sublist:
        Collection<String> c2 = new ArrayList<String>(subList);    
            
        try {
            c.retainAll(c2);
        } catch (Exception e) {
            System.out.println("retainAll(): " + e);
        }        try {
            c.removeAll(c2);
        } catch (Exception e) {
            System.out.println("removeAll(): " + e);
        }        try {
            c.clear();
        } catch (Exception e) {
            System.out.println("clear(): " + e);
        }        try {
            c.add("X");
        } catch (Exception e) {
            System.out.println("add(): " + e);
        }        try {
            c.addAll(c2);
        } catch (Exception e) {
            System.out.println("addAll(): " + e);
        }        try {
            c.remove("C");
        } catch (Exception e) {
            System.out.println("remove(): " + e);
        }        // The List.set() method modifies the value but
        // doesn’t change the size of the data structure:
        try {
            list.set(0, "X");
        } catch (Exception e) {
            System.out.println("List.set(): " + e);
        }
    }    public static void main(String[] args) {
        List<String> list = Arrays.asList("A B C D E F G H I J K L".split(" "));

        test("Modifiable Copy", new ArrayList<String>(list)); // 产生新的尺寸可调的
                                                                
                                                                
                                                               // ArrayList

        test("Arrays.asList()", list); // 产生固定尺寸的 ArrayList

        test("unmodifiableList()",
                Collections.unmodifiableList(new ArrayList<String>(list))); // 产生不可修改的列表
    }
} /* Output: 
--- Modifiable Copy --- 

--- Arrays.asList() --- 
retainAll(): java.lang.UnsupportedOperationException 
removeAll(): java.lang.UnsupportedOperationException 
clear(): java.lang.UnsupportedOperationException 
add(): java.lang.UnsupportedOperationException 
addAll(): java.lang.UnsupportedOperationException 
remove(): java.lang.UnsupportedOperationException 

--- unmodifiableList() --- 
retainAll(): java.lang.UnsupportedOperationException 
removeAll(): java.lang.UnsupportedOperationException 
clear(): java.lang.UnsupportedOperationException 
add(): java.lang.UnsupportedOperationException 
addAll(): java.lang.UnsupportedOperationException 
remove(): java.lang.UnsupportedOperationException 
List.set(): java.lang.UnsupportedOperationException
登录后复制

   因为 Arrays.asList() 实际上会产生一个 Arraylist ,它基于一个固定大小的数组,仅支持那些不会改变数组大小的操作。所以,任何会引起对底层数据结构的尺寸进行修改的方法(add/remove 相关)都会产生一个 UnsupportedOperationException 异常,以表示对该容器未获支持操作的调用。

   因此,Arrays.asList() 的真正意义在于:将其结果作为构造器参数传递给任何 Collection (或者使用 addAll 方法、Collections.addAll 静态方法),这样可以生成一个动态的容器

   由以上程序片段可知, Arrays.asList() 返回固定尺寸的List,而 Collections.unmodifiableList() 产生不可修改的列表。正如输出所示,前者支持 set 操作,而后者不支持。若使用接口,那么还需要两个附加的接口,一个具有可以工作的 set 方法,另一个没有,因为附加的接口对于 Collection 的各种不可修改子类型来说是必须的。因此,可选方法可以避免 接口爆炸

   针对 Arrays.asList() 这种情况给出解释:

1.首先该方法的源码为:

  public static <T> List<T> asList(T... a) {    return new ArrayList<T>(a);
    }
登录后复制

2.紧接着看上述方法所返回的由固定尺寸的数据结构支持的容器源码(部分):

private static class ArrayList<E> extends AbstractList<E>    
implements RandomAccess, java.io.Serializable
    {
    private static final long serialVersionUID = -2764017481108945198L;   
     private final E[] a;

    ArrayList(E[] array) {            
    if (array==null)                
    throw new NullPointerException();
        a = array;
    }    public int size() {       
     return a.length;
    }    public Object[] toArray() {       
     return a.clone();
    }    public <T> T[] toArray(T[] a) {       
     int size = size();        
    if (a.length < size)        
    return Arrays.copyOf(this.a, size,
                     
                     (Class<? extends T[]>) a.getClass());
        System.arraycopy(this.a, 0, a, 0, size);        
        if (a.length > size)
        a[size] = null;        
        return a;
    }    public E get(int index) {        
    return a[index];
    }    public E set(int index, E element) {        
    //该容器支持的操作
        E oldValue = a[index];
        a[index] = element;        
        return oldValue;
    }    public int indexOf(Object o) {        
    if (o==null) {            
    for (int i=0; i<a.length; i++)                
    if (a[i]==null)                    
    return i;
                } else {                    
                for (int i=0; i<a.length; i++)                        
                if (o.equals(a[i]))                            
                return i;
                }        
                return -1;
    }    
    public boolean contains(Object o) 
    {        
    return indexOf(o) != -1;
    }
}

....
其余代码省略
....
登录后复制

针对 Add 操作: 该容器的该行为继承于 AbstractList 抽象类,直接或间接调用 add(int index, E element) 方法,抛出 UnsupportedOperationException

// AbstractList 中的方法public boolean add(E e) {
    add(size(), e);    return true;
    }public void add(int index, E element) {    throw new UnsupportedOperationException();
}public boolean addAll(int index, Collection<? extends E> c) {    boolean modified = false;
    Iterator<? extends E> e = c.iterator();    while (e.hasNext()) {
        add(index++, e.next());
        modified = true;
    }    return modified;
}
登录后复制

针对 remove 操作: 该容器的 remove 相关行为间接继承自 AbstractCollection 类, AbstractList 类并未完全重写(只重写了 clear 操作)它们,如下:

    //AbstractList 类中方法:
    //该方法继承自 List 接口的:remove(int index) 方法,是 List 特有的方法
    public E remove(int index) {    throw new UnsupportedOperationException();
    }    //AbstractList 类重写了 AbstractCollection 的 clear 方法
     public void clear() {
        removeRange(0, size());
    }   protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();           //直接调用了具体容器的迭代器(由 iterator() 方法返回)的 remove 方法   
        }
    }
登录后复制

   AbstractList 类未重写 remove(Object),removeAll(Collection) ,retainAll(Collection) ,这些方法实际上继承自 AbstractCollection 类:

    //AbstractCollection 类中方法:
    public boolean remove(Object o) {
    Iterator<E> e = iterator();    if (o==null) {        while (e.hasNext()) {        if (e.next()==null) {
            e.remove();            return true;
        }
        }
    } else {        while (e.hasNext()) {        if (o.equals(e.next())) {
            e.remove();           //直接调用了具体容器的迭代器(由 iterator() 方法返回)的 remove 方法   
            return true;
        }
        }
    }    return false;
    }public boolean removeAll(Collection<?> c) {    boolean modified = false;
    Iterator<?> e = iterator();    while (e.hasNext()) {        if (c.contains(e.next())) {
        e.remove();           //直接调用了具体容器的迭代器(由 iterator() 方法返回)的 remove 方法   
        modified = true;
        }
    }    return modified;
    } public boolean retainAll(Collection<?> c) {    boolean modified = false;
    Iterator<E> e = iterator();    while (e.hasNext()) {        if (!c.contains(e.next())) {
        e.remove();            //直接调用了具体容器的迭代器(由 iterator() 方法返回)的 remove 方法          
        modified = true;
        }
    }    return modified;
    }
登录后复制

   由上面两段代码可知,remove(Object),removeAll(Collection) ,retainAll(Collection) 和 clear() 这四种操作均直接调用了具体容器的迭代器(由 iterator() 方法返回)的 remove 方法 ,我们再看 AbstractList 类提供的 Iterator 中的 remove 方法:

   private class Itr implements Iterator<E> {
    /**
     * Index of element to be returned by subsequent call to next.
     */
    int cursor = 0;    /**
     * Index of element returned by most recent call to next or
     * previous.  Reset to -1 if this element is deleted by a call
     * to remove.
     */
    int lastRet = -1;    /**
     * The modCount value that the iterator believes that the backing
     * List should have.  If this expectation is violated, the iterator
     * has detected concurrent modification.
     */
    int expectedModCount = modCount;    
    public boolean hasNext() 
    {            
    return cursor != size();
    }    public E next() 
    {
            checkForComodification();        
            try {
        E next = get(cursor);
        lastRet = cursor++;        
        return next;
        } 
        catch (IndexOutOfBoundsException e) 
        {
        checkForComodification();        
        throw new NoSuchElementException();
        }
    }    public void remove() {        
    if (lastRet == -1)        
    throw new IllegalStateException();
            checkForComodification();        
            try {
        AbstractList.this.remove(lastRet);            
        //直接调用 AbstractList 容器的 remove(int index) 方法,抛出 UnsupportedOperationException      
        if (lastRet < cursor)
            cursor--;
        lastRet = -1;
        expectedModCount = modCount;
        } catch (IndexOutOfBoundsException e) {        
        throw new ConcurrentModificationException();
        }
    }    final void checkForComodification() {        
    if (modCount != expectedModCount)        
    throw new ConcurrentModificationException();
    }
    }
登录后复制

    综上可知,示例中的 Arrays.asList() 部分为何会导致那样的结果。

以上就是Java Collection Framework -Collection接口的具体详解的详细内容,更多请关注php中文网其它相关文章!

Java Collection 【对抗遗忘系列】 - 对Collection不断的梳理

Java Collection 【对抗遗忘系列】 - 对Collection不断的梳理

           

Java2的集合框架,抽其核心,主要有三种:List、Set和Map。如下图所示: 

需要注意的是,这里的 Collection、List、Set和Map都是接口(Interface),不是具体的类实现。 List lst = new ArrayList(); 这是我们平常经常使用的创建一个新的List的语句,在这里, List是接口,ArrayList才是具体的类。 


常用集合类的继承结构如下: 

Collection<--List<--Vector 

Collection<--List<--ArrayList 

Collection<--List<--LinkedList 

Collection<--Set<--HashSet 

Collection<--Set<--HashSet<--LinkedHashSet 

Collection<--Set<--SortedSet<--TreeSet 

Map<--SortedMap<--TreeMap 

Map<--HashMap 

-----------------------------------------------SB分割线------------------------------------------ 

List: 

List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下 >标)来访问List中的元素,这类似于Java的数组。 


Vector: 

基于数组(Array)的List,其实就是封装了数组所不具备的一些功能方便我们使用,所以它难易避免数组的限制,同时性能也不可能超越数组。所以,在可能的情况下,我们要多运用数组。另外很重要的一点就是Vector是线程同步的(sychronized)的,这也是Vector和ArrayList 的一个的重要区别。 

ArrayList: 

同Vector一样是一个基于数组上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector好一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。 

LinkedList: 

LinkedList不同于前面两种List,它不是基于数组的,所以不受数组性能的限制。 

它每一个节点(Node)都包含两方面的内容: 

1.节点本身的数据(data); 

2.下一个节点的信息(nextNode)。 

所以当对LinkedList做添加,删除动作的时候就不用像基于数组的ArrayList一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了,这是LinkedList的优势。 

List总结: 

所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ]

所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]

所有的List中可以有null元素,例如[ tom,null,1 ]

基于Array的List(Vector,ArrayList)适合查询,而LinkedList 适合添加,删除操作

-------------------------------------------------------------------------- 


Set: 

Set是一种不包含重复的元素的无序Collection。 

HashSet: 

虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在 HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。看看 HashSet的add(Object obj)方法的实现就可以一目了然了。 

Java代码  收藏代码

public boolean add(Object obj) {   

   return map.put(obj, PRESENT) == null;   

}   

这个也是为什么在Set中不能像在List中一样有重复的项的根本原因,因为HashMap的key是不能有重复的。 

LinkedHashSet: HashSet的一个子类,一个链表。 

TreeSet: SortedSet的子类,它不同于HashSet的根本就是TreeSet是有序的。它是通过SortedMap来实现的。 

Set总结: Set实现的基础是Map(HashMap)

Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象

-------------------------------------------------------------------------- 


Map: 

Map 是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个 Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求,你可以将任意多个键都映射到一个值对象上,这不会发生任何问题(不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象)。 


Map有两种比较常用的实现:HashMap和TreeMap。 


HashMap也用到了哈希码的算法,以便快速查找一个键, 


TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。 

键和值的关联很简单,用put(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。 


-------------------------------------------------------------------------- 


其它: 

一、几个常用类的区别 

1.ArrayList: 元素单个,效率高,多用于查询 

2.Vector: 元素单个,线程安全,多用于查询 

3.LinkedList:元素单个,多用于插入和删除 

4.HashMap: 元素成对,元素可为空 

5.HashTable: 元素成对,线程安全,元素不可为空 


二、Vector、ArrayList和LinkedList 

大多数情况下,从性能上来说ArrayList最好,但是当集合内的元素需要频繁插入、删除时LinkedList会有比较好的表现,但是它们三个性能都比不上数组,另外Vector是线程同步的。所以: 

如果能用数组的时候(元素类型固定,数组长度固定),请尽量使用数组来代替List; 

如果没有频繁的删除插入操作,又不用考虑多线程问题,优先选择ArrayList; 

如果在多线程条件下使用,可以考虑Vector; 

如果需要频繁地删除插入,LinkedList就有了用武之地; 

如果你什么都不知道,用ArrayList没错。 


三、Collections和Arrays 

在 Java集合类框架里有两个类叫做Collections(注意,不是Collection!)和Arrays,这是JCF里面功能强大的工具,但初学者往往会忽视。按JCF文档的说法,这两个类提供了封装器实现(Wrapper Implementations)、数据结构算法和数组相关的应用。 

想必大家不会忘记上面谈到的“折半查找”、“排序”等经典算法吧,Collections类提供了丰富的静态方法帮助我们轻松完成这些在数据结构课上烦人的工作: 

binarySearch:折半查找。 

sort:排序,这里是一种类似于快速排序的方法,效率仍然是O(n * log n),但却是一种稳定的排序方法。 

reverse:将线性表进行逆序操作,这个可是从前数据结构的经典考题哦! 

rotate:以某个元素为轴心将线性表“旋转”。 

swap:交换一个线性表中两个元素的位置。 

…… 

Collections还有一个重要功能就是“封装器”(Wrapper),它提供了一些方法可以把一个集合转换成一个特殊的集合,如下: 

unmodifiableXXX:转换成只读集合,这里XXX代表六种基本集合接口:Collection、List、Map、Set、SortedMap和SortedSet。如果你对只读集合进行插入删除操作,将会抛出UnsupportedOperationException异常。 

synchronizedXXX:转换成同步集合。 

singleton:创建一个仅有一个元素的集合,这里singleton生成的是单元素Set, 

singletonList和singletonMap分别生成单元素的List和Map。 

空集:由Collections的静态属性EMPTY_SET、EMPTY_LIST和EMPTY_MAP表示。 

这次关于Java集合类概述就到这里,下一次我们来讲解Java集合类的具体应用,如List排序、删除重复元素。





今天关于比较Java中的两个Collectionjava比较两个集合用什么方法的讲解已经结束,谢谢您的阅读,如果想了解更多关于.Java中Collection的使用、dom – Meteor:当我插入CollectionB时,CollectionA中的元素重新渲染、Java Collection Framework -Collection接口的具体详解、Java Collection 【对抗遗忘系列】 - 对Collection不断的梳理的相关知识,请在本站搜索。

本文标签: