Java 关于集合框架那点事儿

 

 

 1.引入集合框架
  采用数组存在的一些缺陷:
   1.数组长度固定不变,不能很好地适应元素数量动态变化的情况。
   2.可通过数组名.length获取数组的长度,却无法直接获取数组中真实存储的个数。
   3.在进行频繁插入、删除操作时同样效率低下。
 2.Java集合框架包含的内容
  Java集合框架为我们提供了一套性能优良、使用方便的接口和类,它们都位于Java.util包中。
  集合框架是为表示和操作集合而规定的一种统一的标准体系结构。集合框架都包含三大块内容;对外的接口、接口的实现和对集合运算的算法。
   1.接口     List        Map
   2.实现  ArrayList LinkedList   Hashtable HashMap
   3.算法  扩容原理:int newCapacity = oldCapacity + (oldCapacity >> 1);
  Java集合框架中的两大类接口:Collection和Map。其中,Collection又有两个子接口:List和Set。所以通常说Java集合框架共有三大类接口:List、Set和Map。它们的共同点:都是集合接口,都可以用来存储很多对象。它们的区别如下:
   1.Colection接口存储一组不唯一(允许重复)、无序的对象。
   2.Set接口继承Collection接口,存储一组唯一(不允许重复)、无序的对象。
   3.List接口继承Collection接口,存储一组不唯一(允许重复)、有序(以元素插入的次序来放置元素,不会重新排列)的对象。
   4.Map接口存储一组成对的键-值对象,提供key到value的映射。Map中的key不要求有序,不允许重复。value同样不要求有序,但允许重复。
   5.Iterator接口是负责定义访问和遍历元素的接口。

 


2.List接口
 实现List接口的常用类有ArrayList和LinkedList。它们都可以容纳所有类型的对象,包括null,允许重复,并且都保证元素的存储顺序。
 ArrayList对数组进行了封装,实现了对象可变的数组。ArrayList存储数据的方式和数组相同,都是在内存中分配连续的空间。它的优点在于遍历元素和随机访问元素的效率比较高。
 LinkedList采用链表存储方式,优点在于插入、删除元素时效率比较高。它提供了额外的addFirst()、addLast()、removeFirst()和removeLast()等方法,可以在LinkedList的首部或尾部进行插入或删除工作。这些方法使得LinkedList可被用作堆栈或者队列。
 
 1.ArrayList集合类
  总结一下List接口中定义的各种常用方法(也是ArrayList的常用方法)
    List接口中定义的各种常用方法
  方法名称   说明
 boolean add(Object o)  在列表末尾顺序添加元素,起始索引位置从0开始
 
 void add(int index,Object o)    在指定的索引位置添加元素,原索引位置及其后面的元素依次后移
     注意:新添加元素的索引位置必须介于0和列表中元素个数之间
 int size()   返回列表中的元素个数
 Object get(int index)  返回指定索引位置处的元素
     注意:取出的元素是Object类型,使用前需要进行强制类型转换
 boolean contains(Object o) 判断列表中是否存在指定元素
 boolean remove(Object o) 从列表中删除元素
 Object remove(int index) 从列表中删除指定位置元素,起始索引位置从0开始
 
 2.LinkedList集合类
    LinkedList的一些特殊方法
  方法名称      说明
  void addFirst(Object o)    在列表的首部添加元素
  void addLast(Object o)    在列表的末尾添加元素
  Object getFirst()    返回列表中的第一个元素
  Object getLast()    返回列表中的最后一个元素
  Object removeFirst()    删除并返回列表中的第一个列表
  Object removeLast()    删除并返回列表中的最后一个元素
2.Map接口:
map存储的值叫entry(key+value)
获取map集合key+value值:Set<Map.Entry<K, V>> entrySet()方法
 1.HashMap集合类
    Map的常用方法
  方法名称     说明
 Object put(Object key,Object value)  以"键-值对"的方式进行存储
       注意:键必须是唯一的,值可以重复。如果试图添加重复
       的键,那么最后加入的"键-值对"将替换掉原先的"键-值       队"
 Object get(Object key)    根据键返回相关联的值,若不存在指定的键,则返回       null
 Object remove(Object key)   删除指定的键映射的"键-值对"
 
 int size()     返回元素个数
 Set keySet()     返回键的集合
 Collection values()    返回值的集合
 boolean containsKey(Object key)   若存在指定的键映射的"键-值对",则返回true
 boolean isEmpty()    若不存在键-值映射关系,则返回true
 void clear()     从此映射中移除所有映射关系

应用:

1.Map接口专门处理键值映射数据的存储,可以根据键实现对值的操作,最常用的实现类是HashMap
2.对HashMap类的多个测试

 
import java.util.Map;//接口
import java.util.HashMap;////声明Map接口下的类
    Map countris  = new HashMap();
    //添加 put(Object key键名,Object value值)
    coutries.put("CN","中华人民共和国");
    coutries.put("RU","俄罗斯联邦");
    coutries.put("FR","法兰西共和国");
    coutries.put("US","美利坚合众国");
    //通过key获得值
    String coutry = (String)coutries.get("CN");
    System.out.println(country);
    //显示集合中的个数
    System.out.println(countries.size());
    //两次判断Map接口中是否存在FR  键名
    boolean bo = countries.containsKey("FR");
    System.out.println(bo)如果返回是true代表存在,否则不存在;
    //判断值是否存在
    boolean bov = countries.containaValue("中华人民共和国");
    System.out.println(bov);如果返回值为true,则存在,否则相反
    //删除集合对象
    countries.remove("FR");    
    //遍历,分别显示键集,值集,键值对集合
    System.out.println(countries.keySet());
    System.out.println(countires.Values());
    //键对
    System.out.println(countries);
    //foreach遍历---键值。。。。若想知道值集,则.values即可
    for(Object string : countires.keySet()){
        String keyz = (String)obj;
        System.out.println(keyz);
    }
    //清空HashMap判断
    countires.clear();
    if(countries.isEmpty()){
        System.out.println("已经将所有的HashMap删除");
    }

 

2.Hashtable集合类:

(1)Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射。

(2)Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。

(3)Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。

使用方法与HashMap大相径庭


3.  Hashtable和HashMap的异同:

(1)HashMap是非线程安全的,HashTable是线程安全的。

(2)HashMap的键和值都允许有null存在,而HashTable则都不行。

(3)因为线程安全、哈希效率的问题,HashMap效率比HashTable的要高。

Hashtable和HashMap类有三个重要的不同之处。第一个不同主要是历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。
  
  也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。一个方便的方法就是利用Collections类的静态的synchronizedMap()方法,它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。这个对象的方法可以让你同步访问潜在的HashMap。这么做的结果就是当你不需要同步时,你不能切断Hashtable中的同步(比如在一个单线程的应用程序中),而且同步增加了很多处理费用。
  
  第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。如果有必要,用containKey()方法来区别这两种情况。

 

Vector简介

Vector 是矢量队列,它是JDK1.0版本添加的类。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。
Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能
Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。

和ArrayList不同,Vector中的操作是线程安全的

异同总结:

Vector和ArrayList的异同
 实现原理、功能相同,可以互用
 主要区别:
  Vector线程安全,ArrayList重速度轻安全,线程非安全
  长度需增长时,Vector默认增长一倍,ArrayList增长50%

一、从存储数据的方式来看:

1、ArrayList是采用数组方式存储数据,实现了可变大小的数组。

它允许所有元素,包括null。

其特点:

(1)ArrayList没有同步。

(2)此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以索引数据快插入数据慢。

2、Vector也是采用数组方式存储数据,由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差。

其特点:

(1)Vector是同步的。

(2)由Vector创建的Iterator,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

二、从存取操作的效率来看

  在取数据操作中Arraylist最快。

  在存数据操作中 linklist最快。

  在删除数据操作中linklist最快。

三、从应用的角度来看:
    如果需要快速随机访问元素,应该使用ArrayList。
  如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。


  Hashtable和HashMap的异同
 实现原理、功能相同,可以互用


 主要区别:
  Hashtable继承Dictionary类,HashMap实现Map接口
  Hashtable线程安全,HashMap线程非安全
  Hashtabel不允许null值,HashMap允许null值

 开发过程中,最好使用ArrayList和HashMap

 

4.迭代器Iterator
 所有集合接口和类都没有提供相应的遍历方法,而是把遍历交给迭代器Iterator完成。Iterator为集合而生,专门实现集合的遍历。它隐藏了各种集合实现类的内部细节,提供了遍历集合的统一编程接口。
 Collection接口的iterator()方法返回一个Iterator,然后通过Iterator接口的两个方法即可方便地实现遍历。
  1.boolean hasNext():判断是否存在另一个可访问的元素
  2.Object next():返回要访问的下一个元素
 1.使用Iterator遍历集合类
  资料:JDK1.5加入了增强型for循环,它是for语句的特殊简化版本,我们通常称之为foreach语句,它在遍历数组、集合方面提供了极大的方便。foreach的语句格式:
   for(元素类型t 元素类型x:数组或集合对象){
    引用了x的Java语句
   }
  其中,“t”的类型必须属于“数组或集合对象”的元素类型

注:见到迭代器遍历就使用while循环遍历

补充:遍历集合的几种方式:

1.foreach遍历
 2.迭代器
  通过迭代器Iterator实现遍历
      获取Iterator:Collection接口的iterate()方法
   Iterator的方法
      boolean hasNext():判断是否存在另一个可访问的元素
      Object next():返回要访问的下一个元素

    //1.迭代器方式

    导包:import java.util.Set;
        import java.util.Iterator;
    
    Dog dog1 = new Dog("兰兰",100,90,"拉不拉");
    Dog dog2 = new Dog("楠楠",100,90,"雪纳瑞");
    Dog dog3 = new Dog("娜娜",100,90,"拉不拉");
    Dog dog4 = new Dog("妮妮",100,90,"拉不拉");
    Dog dog5 = new Dog("静静",100,90,"拉不拉");
    Map dogMap = new HashMap();
    dogMap.put(dog1.getName(),dog1);
    dogMap.put(dog2.getName(),dog2);
    dogMap.put(dog3.getName(),dog3);
    dogMap.put(dog4.getName(),dog4);
    dogMap.put(dog5.getName(),dog5);
    //使用Iterator遍历所有的信息
    //迭代器方式
    Set key =  dogMap.keySet();
    //获得Iterator对象
    Iterator it = key.iterator();
    while(it.hasNext()){
        String key = (String)it.next();//获得键名
        System.out.println(key);
        Dog dog = (Dog)dogMap.get(key);
        dog.print();//调用Dog类中的一个自述方法
    }

    //2.for增强版
    for(Object key : keys){
        Dog dog = (Dog)dogMap.get(key);
    }

 

System.ouMap<String, String> map = new HashMap<String, String>();
map.put("s", "sa");
t.print1n("最后的晚餐=============");
//方案三: 使用迭代器遍历key+value同时遍历
iterator2 = map.entrySet().iterator( );|
Iterator<Entry<String,String>>
//见到Iterator就得使用while循环
while(iterator2.hasNext()){
    Entry<String,String> entry = iterator2.next();
    System.out.println(entry.getKey());
    System.out.println(entry.getValue() );
}

 


 
 数组和集合的主要区别包括以下几个方面:

一:数组声明了它容纳的元素的类型,而集合不声明。这是由于集合以object形式来存储它们的元素。
二:一个数组实例具有固定的大小,不能伸缩。集合则可根据需要动态改变大小。
三:数组是一种可读/可写数据结构没有办法创建一个只读数组。然而可以使用集合提供的ReadOnly方   只读方式来使用集合。该方法将返回一个集合的只读版本。
泛型与集合的区别
泛型听起来很高深的一个词,但实际上它的作用很简单,就是提高c#程序的性能。
比如在计算机中经常用到一些数据结构,如队列,链表等,而其中的元素以前一般这么定义:object a=new object();
这样就带来一个严重的问题,用object来表示元素没有逻辑问题,但每次拆箱、封箱就占用了大量的计算机资源,导致程序性能低下,而这部分内容恰恰一般都是程序的核心部分,如果使用object,那么程序的表现就比较糟糕。
而使用泛型则很好的解决这个问题,本质就是在编译阶段就告诉编译器,数据结构中元素的种类,既然编译器知道了元素的种类,自然就避免了拆箱、封箱的操作,从而显著提高c#程序的性能。
比如List<string>就直接使用string对象作为List的元素,而避免使用object对象带来的封箱、拆箱操作,从而提高程序性能。

 

 随笔:

Java集合框架的三大类接口及其区别

分别为: List、Set 和Map
Set 接口继承Collection 接口,存储一组唯一(不允许重复),无序的对象。
List 接口继承Collection 接口,存储一组不唯一(允许重复),有序(以元素插入的次序来放
置元素,不会重新排列) 的对象。
Map接口存储一组(键一值) 对象,提供key (键) 到value (值) 的映射。Map 中的key
不要求有序,不允许重复。value 同样不要求有序,但允许重复。
Java 中ArrayList 与List的区别
ArrayList 是List 接口的一个具体实现类,它实现了可变大小的数组,在进行随机访问和遍
历元素时,它提供更好的性能。
LinkedList.是List 接口的一个具体实现类,它提供了额外的addFirst()、addLast()、
removeFirst() removeLast()等方法,可以在LinkedList 的首部或尾部进行插入或者删除操
作。而且,相较于ArrayList,在插入或者删除元素时,LinkedList 提供更好的性能。

 

 

 

 

(C) 房上的猫 。 保留所有权利。
 https://www.cnblogs.com/lsy131479/

如需转载,请注明出处!!!

 

posted @ 2018-03-10 10:41  房上的猫  阅读(535)  评论(0编辑  收藏  举报