博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java集合体系
阅读量:5250 次
发布时间:2019-06-14

本文共 10378 字,大约阅读时间需要 34 分钟。

集合:

数学里的概念把若干数据放在一起,看成一个整体;而在面向对象的世界里,为了方便对对象的操作,体现了其如何以哪种方式储存(数据结构),集合是储存对象的 容器!

1、相比与数组:

数组:是JAVA语言内置的数据类型,    它是一个线性的序列,所以它可以快速的访问其他的元素。    但是速度是要有代价的,当你创建了一个数组之后,它的容量就固定了    如果发现有越界现象,会报RuntimeException异常错误数组与集合的一点区别:1:数组是固定长度的;集合可变长度的(自由添加)。2:数组可以存储基本数据类型,也可以存储引用数据类型;        集合只能存储引用数据类型。(对象的引用)3:数组存储的元素必须是同一个数据类型;        集合存储的对象可以是不同数据类型。
View Code

 

 

2、集合体系:

  1.  Collection 接口: 

    有了集合就要对其操作,那么具体操作有哪些?为此,抽取各个容器之共性,将其封装为一个接口,可以从面向对象的概念来理解;

    接口方法看帮助文档:Collection家族中 两个主要下属,List,Set,(同为接口)   

  2. Iterator 接口: (迭代器)

    因为不同容器对于对象的储存细节不同,但是有两点还是相同的:判断是否有,取出来,为此也抽取为接口用来规定这种取出集合的方式;各个集合对接口的实现,其遍历时对外提供 iterator()方法;此返回 iterator 接口的一个直接实现,

      如: abstractList 中,内部类实现了接口  Iterator

        public Iterator<E> iterator() {
          return new Itr();    // 内部类 实现了Iterator
        }

  3. list接口:

    有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复

    具体实现类:

      (1) ArrayList:【查询性】

底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快

      (2) LinkedList:【增删性】

底层的数据结构是链表,线程不同步,增删元素的速度非常快。

      (3) Vector:

底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢

    注意:

对于list集合,底层判断元素是否相同,其实用的是元素自身的equals方法完成的。

所以建议元素都要复写equals方法,建立元素对象自己的比较相同的条件依据。

    List  的示例:

package com.collection;import java.util.*;public class MethodOfList {        public static void main(String args[])    {        method1();        method2();        method3();                methdoOfLinkedList();                selfHasEquals();            }    public static void method1(){        ArrayList al = new ArrayList();        al.add("abc0");        al.add("abc1");        al.add("abc3");        al.add(0, "abc5");           //表明是从  index = 0 时存取的:         al.set(2, "替代");        _iterator(al);                /*    abc5            abc0            替代            abc3        */    }    private static void method2(){        ArrayList al = new ArrayList();        al.add("abc0");        al.add("abc1");        al.add("abc3");                ArrayList all = new ArrayList();        all.add("abc0");        all.add("abc1");        all.add("abc5");                all.retainAll(al);     //           交集        _iterator(all);                /*             abc0            abc1        */        }    private static void method3(){        ArrayList al = new ArrayList();        al.add("abc0");        al.add("abc1");        al.add("abc2");        al.add("abc3");        al.add("abc1");                al.remove("abc1");           //只会remove()最先找到的                _iterator(al);                          System.out.println("4:"+al.get(3)); /*        4:abc1        由此方法我们可以用for循环来迭代,不用迭代器,        但是时间比迭代器慢多了,                List集合因为角标有了自己的获取元素的方式,*/                for(int i = 0; i < al.size(); i++)        {//            System.out.println(al.toString());                System.out.println(al.get(i)) ;            if(i==0)                al.add("临死添加");            if(i==1)                al.set(2, "零食修改");        }                /*abc0        abc2        零食修改        abc1        临死添加        */            }    private static void _iterator(Collection coll) {            /*                    当然:如果嫌弃方法不够的话,可以获得   ListIterator            (List集合特有的迭代器,            该列表迭代器接口具备了对元素的增、删、改、查的动作)            */            for(Iterator iterator = coll.iterator(); iterator.hasNext() ;)        {            /*String s = (String)iterator.next();              System.out.println(s);*/               /*                           假如add(2); ----装箱为Integer,不能转为String                                                     jdk1.5增加了泛型,在编译时期动态查询引用数据类型,               达到与实际主观add的效果() 就是集合内类型一致            */                    System.out.println(iterator.next());        }        System.out.println();    }                public static void methdoOfLinkedList(){        LinkedList
ld = new LinkedList
(); ld.add("1"); ld.add("2"); ld.add("3"); ld.add(null); ld.addFirst("addfirst"); ld.addLast("不就是add么?"); _iterator(ld); /* 新增方法: 获得: getFirst() getLast() ;  获取链表中的第一个元素。如果链表为空,    抛出NoSuchElementException; peekFirst(); 获取链表中的第一个元素。如果链表为空,返回null。 peekLast(); public E getFirst() { if (size==0) throw new NoSuchElementException(); return header.next.element; } 移除: removeFirst() NoSuchElementException; removeLast(); pollFirst();获取链表中的第一个元素,但是会删除链表中的第一个元素。 如果链表为空,返回null。 pollLast();   */ ld.removeAll(ld); //全部移除 _iterator(ld); // System.out.println(ld.getFirst()); System.out.println(ld.peek()); // null } public static void selfHasEquals() { ArrayList
al = new ArrayList
(); Str temp = new Str("2"); al.add(new Str("1")); al.add(new Str("2")); //如果没有覆写equals,,,是不会找到,返回false System.out.println(al.contains(temp)); } }class Str{ String s ; Str(String s){ this.s = s; } /*public boolean equals(Object t){ return this.s.equals(((Str)t).s); }*/ }
View Code

 

 

 

  4. Set接口:

无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性

    (1)  HashSet:【唯一性】

底层数据结构是哈希表,线程是不同步的。无序,高效;对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。

        为什么由这两个实现呢??:

查类库:        HashSet
private transient HashMap
map; private static final Object PRESENT = new Object(); ----> public boolean add(E e) { return map.put(e, PRESENT)==null; } ---> HashMap
----public V put(K key, V value) public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry
e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; } 由上我们也可以知道,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。
View Code

    (2) TreeSet: 【 排序性】

用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。如果元素不具备比较性,在运行时会发生ClassCastException异常。

      Set  的示例:

package com.collection;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;public class MethodOfSet {    public static void main(String args[])    {        testMethodOfHashSet();        testMethodOfTreeSet();        testTime();    }    private static void testMethodOfHashSet()    {        HashSet hs = new HashSet();        hs.add("a");        hs.add("b");        hs.add("a");        _iterator(hs);        /*        b        a        体现无序性 和 唯一性*/        }    private static void testMethodOfTreeSet() {        TreeSet ts = new TreeSet();        ts.add("x");        ts.add("z");        ts.add("y");        ts.add("y");        _iterator(ts);        /*        x        y        z*/        }        private static void  _iterator(Set hs)    {        for(Iterator i = hs.iterator(); i.hasNext();) { System.out.println(i.next()); } System.out.println(); } private static void testTime() { long start ,end ; int temp ; Set
st = new HashSet
(); for(int i = 0; i < 1008611;i++) { st.add(i); } start = System.currentTimeMillis(); for(Iterator
i = st.iterator();i.hasNext();) { temp = i.next(); } end = System.currentTimeMillis(); System.out.println("---iterator:"+(end-start)); start = System.currentTimeMillis(); for(Integer t:st) { temp = t ; } end = System.currentTimeMillis(); System.out.println("---增强 for:"+(end-start)); /* ---iterator:25 ---增强 for:24 二者不相上下: */ } }
View Code

 

 

  5、map接口:

        public interface Map<K,V> 

   所有键值对构成的集合,对此种集合集成为一个接口,便于扩展,Map集合存储和Collection有着很大不同:

    1. Collection一次存一个元素;Map一次存一对元素(一对元素也可以看做一个整体,封装为对象,)。
    2. Collection是单列集合;Map是双列集合。
    3.  Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。

  总之,要保证map集合中键的唯一性。

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

  Map.Entry<K,V>

  一对键值本身看做一个对象,由于有获得键,获得值,两种共性,因此抽离出此接口;getKey() ;getValue() :setValue(V value)

  map的实现类中,含有内部实现类:

    Entry: static class Entry<K,V> implements Map.Entry<K,V>

    so ,entry是访问键值关系的入口,是map的入口,访问的是map中的键值对,

    但由于内部类无法导入,故使用接口回调

  转换:

     map中的所有Entry 转化 为 entrySet (返回:set<Map.Entry<k,v>>

    也可以将所有键值转为: Set keySet();

    Map 的示例:

package com.collection;import java.util.*;public class MethodOfMap {        public static void main(String args[])    {        methodOfHashMap();                    methodOfTreeMap();                Example();    }            private static void methodOfHashMap() {        Map
m = new HashMap
(); m.put(1, "a"); m.put(2, "a"); m.put(3, "a"); m.put(2, "b"); // //出map集合中所有元素 Set
> s1 = m.entrySet(); for(Iterator
> i = s1.iterator(); i.hasNext(); ) { Map.Entry
e = i.next(); System.out.println(e.getKey()+" : "+e.getValue()); e.setValue(e.getKey()+""+e.getValue()); //根据键值来修改: } System.out.println(); Set
s2 = m.keySet(); for(Iterator
i = s2.iterator(); i.hasNext(); ) { Object k = i.next(); Object v = m.get(k); System.out.println(k+" : "+v); } /* 1 : a 2 : b 3 : a 1 : 1a 2 : 2b 3 : 3a */ } private static void methodOfTreeMap() { Map
m = new TreeMap
(); m.put(51, "v"); m.put(72, "e"); m.put(33, "l"); m.put(42, "o"); Set
s = m.keySet(); Iterator
i = s.iterator(); while(i.hasNext()){ Integer k = i.next(); String v = m.get(k); System.out.println(k+"-"+v); }/* 33-l 42-o 51-v 72-e*/ } public static void Example() { /* 一字符串:String str="1,1,0"; 数字使用逗号隔开,统计出每个数字出现的次数。使用map
<数字,次数>
;*/ String target = "10,16,10,16,17,11,16,10,16,10,17,11,16,13,13,11,16,10"; String s[] = target.split(","); Map
m = new HashMap
(); for(int i = 0 ;i
> i = m.entrySet().iterator() ;i.hasNext();) { Map.Entry
me = i.next(); System.out.println(me.getKey()+":"+me.getValue()); /* 10:5 17:2 16:6 13:2 11:3 */ } }}
View Code

 

 

 

转载于:https://www.cnblogs.com/foreverzd/p/3416829.html

你可能感兴趣的文章
python的多行注释
查看>>
连接Oracle需要jar包和javadoc文档的下载
查看>>
UVA 10976 - Fractions Again?!
查看>>
Dreamweaver cc新版本css单行显示
查看>>
【android】安卓的权限提示及版本相关
查看>>
JavaScript可否多线程? 深入理解JavaScript定时机制
查看>>
IOS基础学习
查看>>
Java基础教程——网络基础知识
查看>>
Kruskal基础最小生成树
查看>>
浅谈算法和数据结构: 一 栈和队列
查看>>
【hdu 1429】胜利大逃亡(续)
查看>>
图论-次短路求法
查看>>
What's New for Visual C# 6.0
查看>>
ExtJs学习笔记之ComboBox组件
查看>>
关于收费软件
查看>>
getopt_long
查看>>
TensorFlow MNIST CNN 代码
查看>>
javascript之Style物
查看>>
JSON跨域解决方案收集
查看>>
图的深度优先遍历
查看>>