关于JAVA集合框架的回顾

来源:互联网 发布:深圳软件产业基地 编辑:程序博客网 时间:2024/05/20 19:49
这两天因为要准备笔试,所以好好的回顾了一下所学java内容的基础,发现很多都记不起来了,基础不牢固再往后学就没有意义了,首先啃的就是java集合框架这块大蛋糕。还记得当时学集合框架的时候花了大量的时间,最大的感受就是java中集合这块儿内容真的挺多,学的时候有种崩溃的感觉,不过还是坚持下来了。废话不多说,开始!说起集合,得从java集合的两个顶层接口说起,分别是Collection和Map接口,先说Collection接口,它下面有两个子接口,分别是List接口和Set接口。List:特点是有序,并且其中的元素可以重复,因为该集合有索引。Set:特点是无序,并且不允许有重复的元素。(在这里,所谓的有序或者无序指的是元素的存入顺序和取出顺序是否一样)List集合中的一些常用的共性方法:增:add(int index,E element)   addAll(int index,Collection collection)删:remove(int index)改:set(int index,E element)查:get(int index)   sublist(from,to)//返回列表指定index之间的视图值得一提的是:List集合还有一个它所特有的迭代器,那就是ListIterator,之所以存在这么一个接口来进行扩展,是因为Iterator接口的局限性,由于在使用迭代器进行迭代时不能用集合中的方法来对元素进行操作,但是Iterator接口中所能用的方法又比较少,不能更改删除元素什么的,所以提供了这儿一个接口,具体的迭代方式如下:
ListIterator<String> li = new ListIterator<String>();while(li.hasNext()){    System.out.println(li.next());}

集合里面是有指针的,在没有迭代之前,指针指向的位置是第一个元素之前,在进行了整个迭代过程之后,指针指向的位置是最后一个元素之后。
List接口其下有三个具体实现的子类,分别是ArrayList,LinkedList以及Vector。
ArrayList:很常用的集合类,底层的数据结构是数组,所以特点是查询数据快,但是增删慢,并且线程不同步!
LinkedList:同样也是很常见的集合类,底层的数据结构是链表,所以特点是增删速度很快,但是查询速度很慢,毕竟人家查询时从头开始一个一个的查询。
LinkedList有几个它特有的方法,分别是:addFirst(),addLast(),removeFirst(),removeLast()(关于删除的这两个方法返回的是删除的那个元素,所以,这两个方法也可以用来迭代)。

LinkedList<String> ll = new LinkedList<String>();ll.add("java01");while(!ll.isEmpty()){    System.out.println(ll.removeFirst());}

但是在1.6版本之后,Java对上面的四个LinkedList集合类的特有方法进行了优化,方法名分别变成了:peekFirst(),peekLast(),pollFirst(),pollLast().优化点是:当集合为空进行删除时不会抛出异常,而是返回null.
Vector:被抛弃的集合类,底层的数据结构也是数组,但是和ArrayList不同的是它是线程同步的,所以就这个集合类来说,查询很慢,增删也慢。所以基于这些缺点,逐步被ArrayList所取代,郁郁而终。但是,它涉及到一个独特的遍历集合的方式,那就是枚举!下面用一小段代码来进行阐述!

Vector<String> v = new Vector<String>();v.add("java01");v.add("java02");v.add("java03");//此处返回一个枚举Enumeration en = v.elements();while(en.hasMoreElements()){    System.out.println(en.nextElement());}

下面来说说另外两个集合类遍历集合的方式,List集合遍历一共有三种方式,分别是:
1.普通for循环来进行集合的遍历
2.增强for循环来进行集合的遍历
3.迭代器进行集合的遍历(有两种迭代器,用法都差不多),下面用小段代码来演示List集合迭代器遍历的方式。

ArrayList<String> al = new ArrayList<String>();al.add("abc1");al.add("abc2");al.add("abc3");Iterator<String> it = al.iterator();//此处用for循环来进行迭代会更加的优化,只是个人习惯问题while(it.hasNext()){    System.out.println(it.next());}

如果在List集合中存储自定义对象要求不能重复时,我们所依赖的方法时contains(),但是我们要知道的是contains方法底层调用的是equals方法,要想出现不重复的集合,那么我们必须要重写equals方法!
PS:其实remove底层也是调用的equals方法!
以上就是List集合的大概内容,集合框架的一些方法需要大量的练习才能很好的掌握,因为内容实在是有点多,有很多东西容易混

··············································································································································
List集合说完了,那么下面开始说说Set集合,Set集合的特点是无序,且元素不能重复,它有两个具体实现子类,分别是:
HashSet:看名字就知道,这玩意儿底层的数据结构是哈希表,其实也就是存进去的一个对象对应哈希表中的一个地址值。
要存入自定义对象,那么HashSet集合保证自身集合内元素唯一性的依仗是:hashCode和equals两个方法,在存储自定义对象时,先将要存入的元素和集合中已经存在的元素进行哈希值的比较,如果哈希值不一样,直接往里存,如果哈希值一样,那么要进行equals的判断,判断两个对象是否相同,如果哈希值一样,对象引用的地址不一样,那么后一个对象是前一个对象相同地址下的一个顺延!
TreeSet:TreeSet集合底层的数据结构是二叉树,它的特点是可以对集合中的元素进行排序,有两种情况:
1.当元素自身具备比较性时,拿存入自定义对象为例,要对存储进去的元素进行比较,那么要让存入的自定义对象所对应的类实现Comparable接口,然后在类中重写compareTo方法,集合在存入自定义对象时会自动调用我们已经重写的compareTo方法,从而保证元素的唯一性以及对元素进行排序,得到我们想要的顺序。
2.当元素自身不具备比较性或者具备的比较性不是我们所需要的时候,这时就需要提供另外一种方式来进行比较了,那就是构建比较器类!让该类实现Comparator接口,并且在类中重写compare方法,最后在集合创建时将比较器类的对象作为一个参数传给集合的构造函数,也就是说在集合对象创建时就已经具有了比较性,之后在存入自定义对象时就会遵循这些规则来进行比较,保证元素的唯一性并且对元素进行排序!
PS:两种对集合进行排序的方式同时存在时,以比较器为主!
无论集合的底层是什么数据结构,只要是存入自定义对象进行排序,那么最核心的要点就是:根据条件来重写合适的方法来使集合具备自己想要的比较性。
·················································································································································
最后,来说说集合框架的另外一个顶层接口Map!Map集合
Map集合的特点:集合存储的元素是键值对,它关注事物的映射和键值的唯一性,这句话如何理解呢?意思就是Map集合中键与键之间不能重复,要保证键的唯一性,值的唯一性指的是一个值只能对应一个键,但是值与值之间是可以重复的!
Map集合有很多常用的共性方法:
1.添加:
put(K key,V value);
putAll(Map(? extends K,?extends V) m);
2.删除:
clear();
remove(Object key);
3.判断:
containsValue(Object value);
containsKey(Object key);
isEmpty();
4.获取:
get(Object key);
size();
values();

entrySet();
keySet();
上面的这些都是常用的关于Map集合的方法,增删改查都包含在内,需要深入了解的话还得查查API文档了。
Map集合下面有三个常见的子类对象:
–HashTable:底层的数据结构是哈希表,不可以存入null键或null值,并且该集合是线程同步的,也就是说HashTable这个类是线程安全的,JDK1.0版本就出现了,效率比较低!
–HashMap:底层的数据结构也是哈希表,但是可以存入null键和null值,并且该类是线程不安全的,JDK1.2版本出现的,效率较高!
–TreeMap:底层的数据结构是二叉树,线程不同步,这个类的作用的是对Map集合中的键进行排序!
就效率来说,由高到低的顺序应该是这样的:HashMap>TreeMap>HashTable

下面介绍两种遍历Map集合并且获取其中的键和值的方法:
1.利用keySet()这个获取集合中所有的键并返回一个包含所有键的Set集合的方法!代码演示如下:

import java.util.*;class Demo{    public static void main(String [] args){        TreeMap<String,String> tm = new TreeMap<String,String>();        tm.put("zhangsan","19");        tm.put("lisi","20");        tm.put("wangwu","29");        Set<String> keySet = tm.keySet();//获取Map集合中所有的键,并返回一个Set集合        //用迭代器来对Set集合中的键进行遍历        Iterator<String> it = keySet.iterator();        while(it.hasNext())        {            String key = it.next();//获取键            String value = tm.get(key);//通过get方法获取键对应的值            System.out.println("key="+key+" "+"value="+value);        }    }}

2.使用entrySet()方法来获取集合中的映射关系,并且返回一个存储着映射关系的Set集合,代码演示如下:

import java.util.*;class Demo2{    public static void main(String[] args){        Map<String,String> map = new TreeMap<String,String>();        map.put("zhangsan","20");        map.put("lisi","23");        map.put("wangwu","33");        //用entrySet()方法来获取集合中的所有的映射关系        Set<Map.Entry<String,String>> entrySet = map.entrySet();        Iterator<Map.Entry<String,String>> it = entrySet.iterator();//用迭代器来遍历集合并获取集合中的映射关系        while(it.hasNext())        Map.Entry<String,String> me = it.next();    }}

上一段代码最难理解的点就是Map.Entry

/*Map.Entry是一个接口,并且他是Map接口中的一个内部接口*/interface Map{    public static interface Map.Entry    {        public abstract Object getKey();        public abstract Object getValue();    }}class HashMap implements Map{    class Entry implements Map.Entry    {        public Object getKey(){}        public Object getValue(){}    }}

这是个什么类型呢?为什么要这样去定义呢?
首先先解释一下:Entry是HashMap的一个内部类,并且实现了Map.Entry接口(没错,它是一个接口),那么我们再来看下Map.Entry接口是怎么定义的,其实它是Map的一个内部接口并且定义了一些方法,其中就有getKey(),getValue(),setKey(),setValue();HashMap的底层使用的是Entry数组来存储键值对.

从这里我们其实也可以联想到不光是HashMap,譬如LinkedHashMap,TreeMap 等继承自map的容器存储key-value对都应该使用的是Entry只不过组织Entry的形式不一样,HashMap用的是数组加链表的形式,LinkedHashMap用的是链表的形式,TreeMap应该使用的二叉树的形式

0 0
原创粉丝点击