Java集合小总结(花了一晚上的时间)

来源:互联网 发布:手机计算器软件 编辑:程序博客网 时间:2024/04/30 15:36
java中的Collection是一个集合接口。它提供了对集合进行基本操作的通用接口方法。Collection接口在java类库中有很多具体的实现,其意义在于为各种具体的集合提供了最大化的同一操作方式。
Collections是一个包装类,它包含有各种有关集合操作的静态多态方法,就像是一个工具类,服务于java的Collection框架。

Collection是最基本的集合接口,一个Collection代表一组Object。一些Collection允许相同的元素,而有些不行,一些能排序。所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素,后一个构造函数允许用户复制一个新的Collection。

Collection与数组有两点不同:
1、数组的容量是由限制的,而Collection没有这样的限制,它的容量可以自动调节。
2、Collection只能用于存放对象,数组没有这样的限制,既可以存放对象,也可以存放数据。

Collectin中的一些常用的方法:
add():向集合中添加元素,每add一次就添加一次。
addAll():向集合中添加集合,新集合的长度是两个集合的长度之和。
size():计算集合中元素的个数(即集合的长度)。
isEmpty():判断集合是否为空。
clear():清空集合中的元素,清空后,打印集合显示[]。
contains():判断集合中是否包含指定的元素,如果有就返回true,根据equals方法来判断的。
toArray():把当前集合转变成一个Object型的数组。
containsAll():当前集合如果包含传入集合的所有的元素就返回true。

Collection接口下面派生出来两个子接口 List和Set。

1、List是有序的Collection,使用此接口能够精确的控制每个元素的插入位置。用户能够利用索引(元素在List中的位置)来访问List中的元素,而且List元素有相同的元素。
List接口除了具有Collection接口必备的iterator方法外,List还提供了一个listIterator()方法,和标准的iterator接口相比,ListIterator多了一些add()之类的方法,允许添加、删除、设定元素,还能向前或向后遍历。
实现List接口的常用类有LinkedList、ArrayList、Vector和Stack。

ArrayList类实现了可变大小的数组,它允许所有元素,包括null,线程不同步。此类除了实现了List接口外,还提供了一些方法来操作内部用来存储列表的数组的大小。其底层是可改变大小的数组,特点是:查询快,但是插入、删除、修改都比较慢。当更多的元素添加到ArrayList中时,其大小会动态的增加,内部的元素可以通过get、set方法进行访问。
get(int index):返回此列表中指定位置上的元素。
set(int index,E element):用指定的元素替代此列表中指定位置上的元素。  E:泛型。

LinkedList(不同步)的本质是一个双向链表,特点是:查询较慢,插入、删除对比ArrayList有更好的性能。并且允许所有元素(包括null)。

示例代码:

public class LinkedListDemo01 {public static void main(String[] args) {LinkedList<String>list = new LinkedList<>();list.add("aaa");list.addFirst("bbb");list.addLast("ccc");System.out.println(list);//逆序遍历  是LinkedList当中独有的方法Iterator<String>it = list.descendingIterator();while (it.hasNext()) {String str = it.next();System.out.println(str);} list.offer("fff");System.out.println(list);System.out.println(list.poll());System.out.println(list);//模仿一下进栈出栈的过程     栈:先进后出,后进先出LinkedList<String>list2  = new LinkedList<>();list2.push("xxx");list2.push("yyy");list2.push("zzz");System.out.println(list2);  //[zzz,yyy,xxx]list2.pop();System.out.println(list2);//[yyy,xxx]list2.pop();  //[xxx]list2.pop();System.out.println(list2);}}

Vector类非常类似于ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的是同一个接口,但是因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态,这是调用iterator方法,会抛出ConcurrentModificationException异常。Vector的大小可以根据需求变大或减小。

实例代码:

public class VectorDemo {public static void main(String[] args) {Vector<String>vector = new Vector<>();vector.add("aaa");vector.add("ccc");vector.addElement("xxx");System.out.println(vector);//vector集合遍历的方法Enumeration<String>en = vector.elements();while (en.hasMoreElements()) {String str = en.nextElement();System.out.println(str);}}}
Set接口:Set是一个不包含重复元素的Collection,更正式的而说:Set不包含满足e1.equals(e2)的元素对e1和e2,所有的重复内容是靠hashCode()和euqals()两个方法区分的,并且最多包含一个null元素。而且Set接口没有提供Collection接口额外的方法。

示例代码:

public class SetDemo01 {public static void main(String[] args) {Set set = new HashSet<>();//添加元素set.add("aaa");set.add("bbb");set.add(new String("aaa"));System.out.println(set.size());   //2System.out.println(set);set.add(1);set.add(3);set.add(7);set.add(5);System.out.println(set.add(3));  //falseSystem.out.println(set.size());System.out.println(set);  //[1, 3, aaa, 5, 7, bbb]System.out.println(set.contains("bbb"));  //true//思考一个问题:set集合当中会有get方法么 ?   没有//遍历set集合System.out.println("=======增强for循环=======");for (Object object : set) {System.out.println(object);}System.out.println("======普通for循环=========");Object obj[] = set.toArray();for (int i = 0; i < obj.length; i++) {System.out.println(obj[i]);}System.out.println("=======迭代器=========");Iterator it = set.iterator();while (it.hasNext()) {Object o = it.next();System.out.println(o);}}}

实现Set接口的两个类分别是HashSet和TreeSet。
1、HashSet:
它是根据hash算法求出的值来存储集合中的元素,所以HashSet具有很好的存取和查找性能。当向HashSet中存放一个元素时,其就会调用hashcode方法来获取此对象的hashcode值,然后根据此值来决定该对象在HashSet中存放的位置,如果该hashcode值对应的地址上已经存放了元素,这时通过equals方法来判断这两个元素,如果返回true,就不存储,否则,就添加成功。HashSet集合中的元素的hashcode值可能相同,所以既要用equals方法来比较一下,相同的hashcode值的对象不一定是同一个对象。
特点:
1、不能保证元素的排列顺序,顺序可能与添加的顺序不同,顺序也可能随时发生变化。
2、HashSet不是同步的,如果多个线程同时访问一个HashSet时,必须要通过代码来保证其同步。
3、Set集合中的元素可以是null,但是只能存放一个。
使用注意:
1.HashSet不保存元素加入的顺序。
2.HashSet集合存放,取出,删除对象都很有效率。
3.对于存放在hashset集合当中的对象对应的类,一定要重写equals(obj)和hashcode()方法,以实现对象的相等判断。
4.Hashset是根据元素的hash码进行存放的,取出时也可以根据hash码快速的找到。


2、TreeSet:
TreeSet集合排序不根据元素插入的顺序,而是根据元素值的大小进行排序,与HashSet通过hashcode值来决定存储顺序是不同的,TreeSet是根据红黑树的数据结构来存取集合元素。
TreeSet集合的排序规则:
1、自然排序:和存入到集合中的元素的类型是相关的。
2、定制排序。


TreeSet集合中存放的元素类型的限制:
存入的元素的数据类型必须是相同的。


自然排序:
TreeSet会调用集合元素的compareTo方法比较元素之间的大小关系,然后将元素中的按照升序进行排列,这种方式就叫做自然排序。
java中提供了Comparable接口,接口中定义了compareTo方法,该方法的返回值是整数类型。实现该接口的类必须实现该方法,通过此方法可以实现此类中大小的比较。当一个对象调用该方法时,与另一个对象想比较obj1.compraeTo(obj2),若返回0,相同,若返回正数,就是1>2,(升序)负数,2>1(降序)。
大部分类在实现compraeTo方法时,必须将比较对象强制转换为相同类型。因为只有相同类的两个实例才有可比性。当一个对象存到TreeSet集合中时也就确定了集合的类型,那么TreeSet会调用此对象的compraeTo方法。


结论:向TreeSet集合中存放的数据必须是同一类的实例,否则就会引起ClassCastException的异常。


向TreeSet集合中添加的对象可以是自定义类的对象,但是自定义类必须实现Comparable接口,还要重写compareTo方法。


定制排序:
可以在TreeSet创建对象时,自定义比较器,
创建TreeSet时使用带参数的构造方法,传入一个比较器的对象。
要实现Comparator<E>  E:对象类型
如:

示例代码:

import java.util.Comparator;//要求:1.成绩从高到低。//2.如果成绩相同,年龄从小到大,//3.如果年龄一致,字典顺序姓名。//4如果姓名也一致,就同一对象。public class StudentComparator implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {if (o1.getScore()>o2.getScore()) {return -1;}else if (o1.getScore()<o2.getScore()) {return 1;}else {if (o1.getAge()>o2.getAge()) {return 1;}else if (o1.getAge()<o2.getAge()) {return -1;}else {return o1.getName().compareTo(o2.getName());}}}}

Map:
Map集合是用于保存具有映射关系的数据,其中保存的其实是两组数,一组保存的是Map中的key值,另一组保存的是values值。Map并没有继承Collection接口,而且一个Map中不能包含相同的key,每个key只能映射一个value。
如果把Map中所有的key值放到一起看,那就形成了set


集合(所有key值没有顺序,且不能重复)。
所有的value值放到一起看,就相当于一个list集合,


元素和元素之间是可以重复的,List集合中可以通过整


数的索引拿到对应的值,Map中取出数据通过另外一个


对象作索引,那就是key值,因此,Map集合有时可以被


称之为字典,或者关联数组。
Map当中的常用方法:
 * put: 向map集合当中添加元素,传值key-value;
 * get:返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
containsKey:判断map集合当中是否包含指定的Key值。
containsValue:判断map集合当中是否包含一个或者多个指定的value值。
keySet:返回map集合当中的key所组成的set的集合
values:返回map当中所有的value值所组成的Collection
equals:比较map当中的映射关系是否相同
isEmpty:判断该map的内容是否为空
putAll:将指定的map的键值对复制到本map当中。
remove:移除指定的key值对应的key-value对,如果key值存在,返回值为对应的value值。
size:map当中键值对的数量
clear:删除map当中所有的key-value键值对。


TreeMap其实就是一个红黑树的数据结构,TreeMap在存储key-value时会对节点进行排序。
TreeMap会保证所有的key-value都处于有序的状态。
两种排序方式:
1、自然排序:TreeMap中的key值所属的类都实现了comparable接口,且所有的key都是同一个类的对象。
2、定制排序:创建TreeMap时,使用有参的构造,传入一个实现了comparator接口的对象,这个对象负责将TreeMap中的所有的key值排序,如果采用了定制排序,就不要求TreeMap当中的key值所属的类实现compareble接口了。

示例代码:

public class Person implements Comparable<Person>{private String name;private int age;@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}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 Person(String name, int age) {super();this.name = name;this.age = age;}/** * 1.年龄升序排序,如果年龄相同就按照姓名排序。 * */@Overridepublic int compareTo(Person o) {if (this.age>o.age) {return 1;}else if (this.age<o.age) {return -1;}else {return this.name.compareTo(o.name);}}}

TreeMap当中判断两个映射关系是否相同的依据,也是通过重写compareTo方法,如果返回值为0,就认为相同。

[HashSet  HashMap  Hashtable三者之间的区别和联系]
1.HashSet的底层使用了HashMap来实现,但是hashset没有key-value映射关系。
HashMap当中有key-value视图,HashSet当中是不允许出现重复对象的。
2.Hashtable是基于Dictionary这个类的,HashMap是基于AbstractMap,都是Map接口的实现类。
3.Hashtable是同步的,,是线程安全的,而HashMap是不同步的,是线程不安全的。
4.HashMap当中key和value都可以为空值,但是因为HashMap的key值是不允许重复的,
所以key最多只能一个null值。但是value可以有多个空值。
Hashtable就不允许有null,无论是key,还是value。
5.内存初始化大小不同,使用无参数的构造创建对象时,Hashtable初始化长度为11,HashMap初始化长度16.
6.内存扩充时采用的方式也不同,Hashtable :2*old+1   HashMap:2*old
7.hash值计算方式不同,Hashtable是直接使用了对象的hashcode,HashMap则在对象的hashcode基础之上进行了一些加工。

6 0