今天来总结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
由于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的古老版本
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,总算是就集合总结完了,有耐心看完的朋友,相信你会收获不小。固然,我这总结的可能也会有很多的漏洞,欢迎大家指导。睡觉了。