JAVA中的集合类
来源:互联网 发布:运动软件免费下载 编辑:程序博客网 时间:2024/06/05 23:00
集合类存放于java.util包中。
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)。
集合类型主要有3种:set(集)、list(列表)和map(映射)。
1. List
- 所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ];
- 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ];
- 所有的List中可以有null元素,例如[ tom,null,1 ];
- 基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操作。
继承关系
Collection<–List<–Vector
Collection<–List<–ArrayList
Collection<–List<–LinkedListVector:
基于Array的List,其实就是封装了Array所不具备的一些功能方便我们使用,它不可能走出Array的限制。性能也就不可能超越Array。所以,在可能的情况下,我们要多运用Array。另外很重要的一点就是Vector是线程安全的,这个也是Vector和ArrayList的唯一的区别。ArrayList:
ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。默认初始容量为10。随着ArrayList中元素的增加,它的容量也会不断的自动增长。在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,扩容操作带来数据向新数组的重新拷贝,所以如果我们知道具体业务数据量,在构造ArrayList时可以给ArrayList指定一个初始容量,这样就会减少扩容时数据的拷贝问题。当然在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。注意,ArrayList实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。所以为了保证同步,最好的办法是在创建时完成,以防止意外对列表进行不同步的访问:
List list = Collections.synchronizedList(new ArrayList(...));
ArrayList源码分析:
http://blog.csdn.net/u011280067/article/details/77731729LinkedList:
LinkedList不同于前面两种List,它不是基于Array的,所以不受Array性能的限制。它每一个节点(Node)都包含两方面的内容:
1.节点本身的数据(data);
2.下一个节点的信息(nextNode)。
所以当对LinkedList做添加,删除动作的时候就不用像基于Array的List一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了。这就是LinkedList的优势
2. Set
- Set实现的基础是Map(HashMap,非线程安全);
Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象
继承关系
Collection<–Set<–HashSet
Collection<–Set<–HashSet<–LinkedHashSet
Collection<–Set<–SortedSet<–TreeSet- HashSet:
HashSet是基于HashMap来实现的,底层采用HashMap的key来保存元素,定义一个虚拟的 Object 对象作为 HashMap 的 value。因为是用HashMap的key存储HashSer的元素,所以HashSet中的元素不可以重复,代码如下
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable{ static final long serialVersionUID = -5024744406713321676L; // 初始化 HashSet,底层会初始化一个 HashMap private transient HashMap<E,Object> map; // 定义一个虚拟的object作为HashMap的value private static final Object PRESENT = new Object(); // 默认构造函数 // 初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。 public HashSet() { map = new HashMap<>(); } // 构造一个包含指定 collection 中的元素的新 set。 public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int)(c.size()/.75f) + 1, 16)); addAll(c); } // 构造一个新的空 set // 其底层 HashMap 实例具有指定的初始容量和指定的加载因子 public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } // 构造一个新的空 set // 其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。 public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } // 访问权限为包权限,不对外公开的一个构造函数 // 为了子类linkedHashSet初始化时调用 // 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。 // dummy 为标识 该构造函数主要作用是对LinkedHashSet起到一个支持作用 HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity,loadFactor); } // 调用map的keySet来返回所有的key public Iterator<E> iterator() { return map.keySet().iterator(); } // 调用HashMap的size()方法返回Entry的数量就得到该Set里元素的个数 public int size() { return map.size(); } // 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空, // 当 HashMap 为空时,对应的 HashSet 也为空 public boolean isEmpty() { return map.isEmpty(); } // 调用 HashMap 的 containsKey 判断是否包含指定 key //HashSet 的所有元素就是通过 HashMap 的 key 来保存的 public boolean contains(Object o) { return map.containsKey(o); } // 将指定元素放入HashSet中也就是将该元素作为key 放入HashMap public boolean add(E e) { return map.put(e, PRESENT) == null; } //调用HashMap的remove方法删除指定Entry也就删除了HashSet中对应的元素 public boolean remove(Object o) { return map.remove(o)==PRESENT; } // 调用Map的clear方法清空所有Entry也就清空了HashSet中所有元素 public void clear() { map.clear(); } ...... }
- LinkedHashSet
LinkedHashSet是基于链表实现的,保证了存取顺序的一致,在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
LinkedHashSet它继承与HashSet、又基于LinkedHashMap来实现的。它的底层使用LinkedHashMap来保存所有元素,是通过调用父类的构造器底层构造一个LinkedHashMap来实现的。在相关操作上与父类HashSet的操作相同,直接调用父类HashSet的方法即可。LinkedHashSet的源代码如下:
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, java.io.Serializable { private static final long serialVersionUID = -2851667679971038690L; /** * 构造一个带有指定初始容量和加载因子的新空链接哈希set。 * * 底层会调用父类的构造方法,构造一个有指定初始容量和加载因子的LinkedHashMap实例。 * @param initialCapacity 初始容量。 * @param loadFactor 加载因子。 */ public LinkedHashSet(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor, true); } /** * 构造一个带指定初始容量和默认加载因子0.75的新空链接哈希set。 * * 底层会调用父类的构造方法,构造一个带指定初始容量和默认加载因子0.75的LinkedHashMap实例。 * @param initialCapacity 初始容量。 */ public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); } /** * 构造一个带默认初始容量16和加载因子0.75的新空链接哈希set。 * * 底层会调用父类的构造方法,构造一个带默认初始容量16和加载因子0.75的LinkedHashMap实例。 */ public LinkedHashSet() { super(16, .75f, true); } /** * 构造一个与指定collection中的元素相同的新链接哈希set。 * * 底层会调用父类的构造方法,构造一个足以包含指定collection * 中所有元素的初始容量和加载因子为0.75的LinkedHashMap实例。 * @param c 其中的元素将存放在此set中的collection。 */ public LinkedHashSet(Collection<? extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); }}
在父类HashSet中,专为LinkedHashSet提供的构造方法如下,该方法为包访问权限,并未对外公开。
/** * 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。 * 此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。 * * 实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。 * @param initialCapacity 初始容量。 * @param loadFactor 加载因子。 * @param dummy 标记。 */ HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor); }
- TreeSet
TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向 TreeSet中加入的应该是同一个类的对象。
TreeSet是基于TreeMap实现的,实现源代码如下:
package java.util;public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable{ private static final long serialVersionUID = -2479143000061671589L; /** * The backing map. */ private transient NavigableMap<E,Object> m; // 定义虚拟object private static final Object PRESENT = new Object(); /** * 未公开的构造函数,包访问权限 */ TreeSet(NavigableMap<E,Object> m) { this.m = m; } /** * 默认构造函数,实例化一个TreeMap */ public TreeSet() { this(new TreeMap<E,Object>()); } /** * 带Comparator参数的构造函数 * 根据指定比较器进行排序 */ public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } /** * 带Collection的构造函数 * 按照其元素的自然顺序进行排序 */ public TreeSet(Collection<? extends E> c) { this(); addAll(c); } /** * 构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet */ public TreeSet(SortedSet<E> s) { this(s.comparator()); addAll(s); } /** * */ public Iterator<E> iterator() { return m.navigableKeySet().iterator(); } /** * */ public Iterator<E> descendingIterator() { return m.descendingKeySet().iterator(); } /** * */ public NavigableSet<E> descendingSet() { return new TreeSet<>(m.descendingMap()); } /** * */ public int size() { return m.size(); } /** * */ public boolean isEmpty() { return m.isEmpty(); } /** * */ public boolean contains(Object o) { return m.containsKey(o); } /** * */ public boolean add(E e) { return m.put(e, PRESENT)==null; } /** * */ public boolean remove(Object o) { return m.remove(o)==PRESENT; } /** * */ public void clear() { m.clear(); } /** * 将指定集合的元素放到set中 */ public boolean addAll(Collection<? extends E> c) { // Use linear-time version if applicable if (m.size()==0 && c.size() > 0 && c instanceof SortedSet && m instanceof TreeMap) { SortedSet<? extends E> set = (SortedSet<? extends E>) c; TreeMap<E,Object> map = (TreeMap<E, Object>) m; Comparator<? super E> cc = (Comparator<? super E>) set.comparator(); Comparator<? super E> mc = map.comparator(); if (cc==mc || (cc != null && cc.equals(mc))) { map.addAllForTreeSet(set, PRESENT); return true; } } return super.addAll(c); } ......}
3. Map
- 射与集或列表有明显区别,映射中每个项都是成对的。映射中存储的每个对象都有一个相关的关键字(Key)对象,关键字决定了
对象在映射中的存储位置,检索对象时必须提供相应的关键字,就像在字典中查单词一样。关键字应该是唯一的。 - 关键字本身并不能决定对象的存储位置,它需要对过一种散列(hashing)技术来处理,产生一个被称作散列码(hash code)的整数值
- 散列码通常用作一个偏置量,该偏置量是相对于分配给映射的内存区域起始位置的,由此确定关键字/对象对的存储位置。理想情况
下,散列处理应该产生给定范围内均匀分布的值,而且每个关键字应得到不同的散列码 - HashMap:
实现一个映象,允许存储空对象,而且允许键是空(由于键必须是唯一的,当然只能有一个)。 - Hashtable:
实现一个映象,所有的键必须非空。为了能高效的工作,定义键的类必须实现hashcode()方法和equal()方法。这个类 是前面java实现的一个继承,并且通常能在实现映象的其他类中更好的使用。 - WeakHashMap:
实现这样一个映象:通常如果一个键对一个对象而言不再被引用,键/对象对将被舍弃。这与HashMap形成对照,映象 中的键维持键/对象对的生命周期,尽管使用映象的程序不再有对键的引用,并且因此不能检索对象。 - TreeMap:
实现这样一个映象,对象是按键升序排列的。
- JAVA中的集合类
- JAVA中的集合类
- JAVA中的集合类
- JAVA中的集合类
- JAVA中的集合类
- JAVA中的集合类 - -
- JAVA中的集合类
- java中的集合类
- Java中的集合类
- JAVA中的集合类
- Java中的集合类
- Java中的集合类
- java 中的集合类
- JAVA中的集合类
- java中的集合类
- Java中的集合类
- java中的集合类
- java 中的集合类
- 每个月1号触发程序
- 文件上传利器SWFUpload使用
- 将json数据映射成对象的处理办法
- io-bufferedReader类
- OpenStack Heat 如何来实现和支持编排
- JAVA中的集合类
- Android开发,自定义View(一)-----入门
- 二维数组练习18_肿瘤面积
- 搭建Nginx+Java环境
- cmd 关闭tomcat
- 推荐系统
- 通过设置chrome浏览器解决跨域问题,在本地进行开发工作
- 软件开发模式介绍和对比(瀑布、迭代、敏捷等)
- 01-Nginx服务器的安装