程序员人生 网站导航

JavaSE:集合总结(Collection,Map)

栏目:php教程时间:2015-03-26 09:29:59

今天来总结JavaSE部份的集合。首先来从整体来看:
这里写图片描述
我们主要要学习的内容:
这里写图片描述
Collection:

Collection(接口): java.util.Collection
|-- List(子接口) :
    |--ArrayList
    |--LinkedList
    |--Vector
|-- Set(子接口)  :
    |--AbstracSet(子接口)
        |--HashSet
            |--LinkedHashSet
    |--SortedSet(子接口)
        |--TreeSet
|-- Queue(子接口) :    

Map:

Map:java.util.Map
Map(接口)
    |--HashMap
        |--linkedHashMap
    |--Hashtable
        |--Properties
    |--TreeMap

1.Collection:

由于Collection是所有集合类的父接口,所以它中的方方法接口和具体实现类都会继承或实现,那末先来学习Collection:
经常使用到的方法:

add(),addAll(),remove(),clear()--> 这两组方法对照着学习记忆。
contains(),isEmpty()
size(), toArray(),iterator()
具体的作用自己去测试下吧。

接下来学习:
1 List子接口,要明白它的特点是:元素有序且可以重复,怎样保证它是有序的呢?通过索引来保证的。
所以 List集合里添加了根据索引来操作集合元素的方法:

get(),set()
indexOf(),lastIndexOf()
subList()
listIterator()

再看看这个结构,我们要学的就是这些内容:

|-- List(子接口) :
    |--ArrayList
    |--LinkedList
    |--Vector

1.1 ArrayList:
是List接口的典型实现类,可以把它看成是1个可变长度的数组
相比于List,也没有增加新的方法,只是实现了List中的方法

注意:
Arrays.asList() 返回的不是ArrayList,而是1个固定长度的List

1.2 LinkedList:
新增加了链表来保护元素的位置(适用于频繁的插入和删除操作)
既然新增了链表结构,那末它肯定新增了方法:

addFirst(),addLast()
getFirst(),getLast()
removeFirst(),removeLast()

1.3 Vector:
是1个古老的类,它是线程安全的,但是效力低于ArrayList,所以现在很少使用。
操作的是element

2 Set 子接口

|-- Set(子接口)  :
    |--AbstracSet(子接口)
        |--HashSet
            |--LinkedHashSet
    |--SortedSet(子接口)
        |--TreeSet

和List的特点恰恰相反,Set中的元素不能是重复的,但是可以是无序的。
Set中并没有提供额外的方法

问题:怎样来保证两个元素是不能重复的?
solution:首先要通过hashCode()方法来比较两个元素的哈希值是不是相同,如果相同,再通过equals()来判断他们的内容是不是相等,若相等,则重复。

固然只有具体的实现类才有承接对象的能力,而Set的这个特点对它的实现类都是适用的。

2.1 HashSet:
是Set接口的典型实现类,通过Hash算法来存取数据,具有很好的查找和存取性能。

2.2 LinkedHashSet:
HashSet的子类,同时增加了链表结构来保护元素的次序,使元素看起来和插入时的顺序1致。
由于增加了链表结构,所以插入的时候效力下降了,而迭代的时候效力提高了

2.3 TreeSet:
是Sorted的子接口,能实现自定义排序
新增的方法:

comparator(),first(),last(),lower(),higer(),subSet(),headSet(),tailSet()

说实话,这么多方法,我只用到了comparator()!!!
自然排序:
TreeSet添加的对象,必须实现Comparable接口,同时实现compareTo()方法

定制排序:
在TreeSet的构造器中指定排序方式
①可以通过Comparator的实现类,这个实现类得实现compare()方法
②可以通过匿名内部类来直接获得Comparator接口的实例
③可以在构造器中传入匿名对象。

/* * 1.请从键盘随机输入10个整数保存到List中,并按倒序、从大到小的顺序显示出来 * * 2.请把学生名与考试分数录入到Map中,并按分数显示前3名成绩学员的名字。 */ @Test public void test3(){ scan = new Scanner(System.in); List<Integer> list = new ArrayList<Integer>(); for(int i = 0; i < 10; i++){ list.add(scan.nextInt()); } Collections.sort(list); Collections.reverse(list); for(Integer i : list){ System.out.println(i); } } /* * 1. 定义1个Employee类, 该类包括:private成员变量name,age,birthday,其中 birthday 为 MyDate * 类的对象; 并为每个属性定义 getter, setter 方法; 并重写 toString 方法输出 name, age, birthday * * MyDate类包括: private成员变量month,day,year;并为每个属性定义 getter, setter 方法; * * 创建该类的 5 个对象,并把这些对象放入 TreeSet 集合中 * 分别按以下两种方式对集合中的元素进行排序,并遍历输出: * * 1). 使Employee 实现 Comparable 接口,并按 name 排序 2). 创建 TreeSet 时传入 * Comparator对象,按生日日期的前后排序。 * * */ @SuppressWarnings("unused") @Test public void test2() { class MyCommparator implements Comparator<Employee> { @Override public int compare(Employee o1, Employee o2) { if (o1.equals(o2)) return 0; else if (o1.getName().equals(o2.getName())) return new Integer(o1.getAge()).compareTo(new Integer(o2 .getAge())); else return o1.getName().compareTo(o2.getName()); } } Comparator<Employee> cpt = new Comparator<Employee>() { @Override public int compare(Employee o1, Employee o2) { if (o1.equals(o2)) return 0; else if (o1.getName().equals(o2.getName())) return new Integer(o1.getAge()).compareTo(new Integer(o2 .getAge())); else return o1.getName().compareTo(o2.getName()); } }; TreeSet<Employee> ts = new TreeSet<Employee>( new Comparator<Employee>() { @Override public int compare(Employee o1, Employee o2) { if (o1.equals(o2)) return 0; else if (o1.getName().equals(o2.getName())) return new Integer(o1.getAge()) .compareTo(new Integer(o2.getAge())); else return o1.getName().compareTo(o2.getName()); } }); ts.add(new Employee("zhangsan", 23, new MyDate(12, 12, 1993))); ts.add(new Employee("zhaoliu", 27, new MyDate(10, 11, 1977))); ts.add(new Employee("wangwu", 25, new MyDate(22, 1, 1989))); ts.add(new Employee("zhaoliu", 27, new MyDate(3, 2, 1993))); ts.add(new Employee("tianqi", 28, new MyDate(2, 4, 1991))); for (Employee t : ts) { System.out.println(t); } } // Collection: List:arrayList linkedList / Set: hashSet->linkedHashSet // treeSet @Test public void test1() { String[] str = new String[5]; for (String s : str) { s = "atguigu"; System.out.println(s); } for (int i = 0; i < str.length; i++) { System.out.println(str[i]); } } @Test public void test() { List<Object> list = new ArrayList<Object>(); list.add(123); list.add("zhang"); for (Object l : list) { System.out.println(l); } Iterator<Object> itor = list.iterator(); while (itor.hasNext()) { System.out.println(itor.next()); } ListIterator<Object> itor1 = list.listIterator(); itor1.add("lisi"); while (itor1.hasNext()) { System.out.println(itor1.next()); } }
/*1. 定义1个Employee类, 该类包括:private成员变量name,age,birthday,其中 birthday 为 MyDate 类的对象; 并为每个属性定义 getter, setter 方法; 并重写 toString 方法输出 name, age, birthday */ public class Employee{ private String name; private int age; private MyDate birthday; public Employee() { } public Employee(String name, int age, MyDate birthday) { this.name = name; this.age = age; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public MyDate getBirthday() { return birthday; } public void setBirthday(MyDate birthday) { this.birthday = birthday; } @Override public String toString() { return "Employee [name=" + name + ", age=" + age + ", birthday=" + birthday + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((birthday == null) ? 0 : birthday.hashCode()); return result; } // @Override // public int compareTo(Employee o) { // if(this == o) // return 0; // else if(this.getName().equals(o.getName())) // return new Integer(this.age).compareTo(new Integer(o.age)); // else // return this.getName().compareTo(o.getName()); // } }
//private成员变量month,day,year;并为每个属性定义 getter, setter 方法; public class MyDate { private int month; private int day; private int year; public MyDate() { } public MyDate(int month, int day, int year) { this.month = month; this.day = day; this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } @Override public String toString() { return "MyDate [month=" + month + ", day=" + day + ", year=" + year + "]"; } }

3 Queue
是1个古老的接口,是线程安全的,效力低,现在很少使用

到这里Collection集合就先告1段落。
接下来该遍历了:

4 集合元素的遍历:
①由于List中有索引,我们可以通过最基本的for循环来完成,只适用于List集合
②增强for循环,适用于所有集合元素
迭代器:Iterator

注意:①迭代器本身没有承接对象的能力,必须通过集合来获得
     ②在使用iterator.next()之前,必须使用iterator.hasNext()进行判断,否则会报NoSuchElementException异常
     ③Enumeration是Iterator的古老版本

2.Map

Map(接口)
    |--HashMap
        |--LinkedHashMap
    |--Hashtable
        |--Properties
    |--TreeMap

1 Map
首先来讲,Map是和Collection同1级的接口,并列存在,其实不是Collection的子接口。Map用来保存具有映照关系的数据:键值对(key->value)
key中不允许有重复的值,可以看成是1个Set集合,判断是不是重复和Set相同;而值得话可以重复

注意理解映照:我昨天的博客“JDBC的进化2“中所说的ORM就是1种映照关系。还记得么?回顾1下:ORM:对象关系映照,没1张表对应这1个类,每列对应1个属性,每行对应1个对象。

方法:

添加、删除操作:
Object put(Object key,Object value)
Object remove(Object key)
void putAll(Map t)
void clear()

元视图操作的方法:
Set keySet()
Collection values()
Set entrySet()

元素查询的操作:
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
boolean equals(Object obj)

1.1 HashMap
①允许null键,null值,但是不能保证映照的顺序
②判断key值是不是重复,和HashSet相同

1.1.1 LinkedHashMap
类似于HashSet和LinkedHashSet的关系

1.2 TreeMap
我是这样理解的,类比于TreeSet,是TreeSet的键值对情势,可以实现自然排序和定制排序

1.3 Hashtable
又是1个古老的类,线程安全,现在很少使用,不允许插入null键值,其余和HashMap类似,我们主要用到它的子类Properties

1.3.1 Properties
是Hashtable的子类,它中的key和value都是String类型的,我们常常用它来读取配置文件信息

Properties pros = new Properties(); pros.load(new FileInputStream("jdbc.properties")); String user = pros.getProperty("user"); System.out.println(user);

Ok,Map也结束了。。。

3 工具类(Collections)
可以操作List,Set,Map的1个工具类
它中的方法全为静态方法:(学了这么多了,1提工具类,我们就知道它都是静态的方法,扩大1下,以后我们自己也能够创建工具类,来操纵我们具体的实体类,你说是否是这样的呢?)
方法:

排序操作:
reverse()
shuffle()
sort()
sort(List, Comparator)指定排序方式
swap()
查找和替换:
max(),min()
frequency() 次数
copy()
replaceAll() 新值替换旧值

到此为止,是否是以为就总结完了?No,其实还没有开始总结,上面的仅仅是回顾。我们来总结。

总结:

没有好的作图工具(思惟导图有很大的局限性,可能也是我研究的不够深),我只能是手画了,有时候图形能表达的东西更多,也更容易理解记忆。
这里写图片描述
先来这1张整体的
这里写图片描述
这里写图片描述
手机像素有点渣,看不清第1张的,可以看下面的两张。
画的不好,但是我认为可以表达意思了。
来,开始的分析:
我是这样分析的,从整体再到具体(思惟),先纵向再横向:
1.Collection 和Map,有甚么联系和区分?
联系:Collection和Map都是java.util下的集合接口,Collection和Map属于同1层次。
区分:Collection中寄存的是1个值(只能可以是任意的对象),而Map中寄存的是键值对(固然键和值,也只能可以是任意对象)
*再往下走,忘画1个Queue了。
2.List和Set和Queue有甚么区分和联系
联系:都是Collection的子接口。
区分:List中的元素是有序的,可以重复的,而Set中的元素是无序的,不可以重复的;Queue是1个古老的类,是线程安全的,现在很少使用。
*Map和他俩不是1个层次的,没法进行比较
3.ArrayList,LinkedList和Vector的区分和联系
联系:都是List的实现类
区分:LinkedList相比于ArrayList增加了链表结构来保护元素的顺序,适用于频繁的插入和删除操作,而迭代速度没有ArrayList快。Vector是1个古老的实现类,是线程安全的,它中的方法和ArrayList类似,但是效力低于ArrayList

*再来比较Set中各个元素
4.HashSet,LinkedHashSet,和TreeSet有甚么区分和联系?
联系:HashSet和TreeSet是Set接口的实现类,LinkedHashSet是HashSet的子类。
区分:HashSet中的对象需要重写hashCode()和equals()方法,来肯定他们是不是重复,TreeSet中添加的对象需实现Comparable接口,或是在TreeSet构造器中指定Comparator接口的实例。相比于HashSet可以插入任意的无序且不重复的元夙来说,TreeSet有自己的排序方式(自然排序和定制排序)。LinkedHashSet相比于HashSet,增加了链表结构,插入和删除数据性能要低于HashSet,但是迭代性能要高于HashSet。

*到比较Map了
5.HashMap和TreeMap,和Hashtable的区分和联系?
联系:都是Map接口的实现类
区分:HashMap中的键都是Set集合,但是可以将HashMap中的键认为成是HashSet,而TreeMap中的键是TreeSet,TreeMap可以按TreeSet中的排序方式来排序。相比于HashMap,Hashtable是1个古老的实现类,它是线程安全的,它不允许插入null键和null值,而HashMap则允许。

最后就是整体的横向对照:
各个实现类的适用处景和效力对照:
首先进行分类:将List,Set和Map分开,由于寄存的内容不相同。
1.List内部比较:
ArrayList: 有索引,遍历相对来讲较快,效力高;插入和删除时,需要移动很多数据,所以较慢,效力低。
LinkedList:有索引,有链表,遍历快,插入和删除效力高,但是增加链表后,需要保护链表也需要1定的资源。
2.Set内部比较
HashSet:无序,插入快,删除快,遍历,非常慢。
TreeSet:插入和删除,和遍历效力不肯定,由于不知道排序的算法有多么复杂,但是我认为,整体来讲它的效力不会高。
LinkedHashSet:插入和删除效力要低于HashSet,由于增加了链表结构,但是迭代速度增加了很多。算是1种平衡吧。用来平衡效力
3.List和Set做比较
List:有索引,相对来讲遍历较快,而插入,删除较慢
Set:无索引,插入和删除非常快,遍历非常慢。

这几个效力的比较是我自己根据他们的理解来判断的,没有学过数据结构和算法,等我学完后,就可以明确的给出1个效力了,得斟酌它们的数据结构和算法复杂度。有兴趣的朋友可以和我1起研究。
4.总结各适用于甚么场景:
上1张图吧(又是自己画的!):
这里写图片描述

5.Map就不做说明了。对照上面的Set,相信你自己也能明白了。
HashMap
TreeMap
LinkedHashMap:

差点忘了,还有1个要补充的:
ListIterator 和Iterator的区分
ListIterator是Iterator的子接口,只适用于List,它可以在遍历的时候增加,设置,移除值,同时它可以逆向遍历。(逆向遍历我没明白,必须将它的指针移到最后,你才可以逆向遍历,相当于,你先正向遍历后,将指针移到最后,才能逆向遍历)

@Test public void test5(){ // when the element is "def", insert "bbb" or modify to "bbbb", and remove "def"; List<String> list = new ArrayList<String>(); list.add("abc"); list.add("def"); list.add("ghi"); ListIterator<String> li = list.listIterator(); while(li.hasNext()){ String str = li.next(); if(str.equals("def")){ // li.add("bbb"); li.set("aaaa"); li.remove(); } } System.out.println(list); }

Ok,总算是就集合总结完了,有耐心看完的朋友,相信你会收获不小。固然,我这总结的可能也会有很多的漏洞,欢迎大家指导。睡觉了。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐