从你的全世界路过-孤独的放逐
集合
一、集合类概述
java.util包中提供了一些集合类,这些集合类又被称为容器。数组也是一种容器,但集合类与数组的不同之处在于数组的长度是固定的,而集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。常用的集合有List集合、Set集合和Map集合,其中List与Set继承了Collections接口。各接口还提供了不同的实现类。
这些类的继承关系如下:
![](https://images2015.cnblogs.com/blog/1135811/201705/1135811-20170513090453972-779454496.png)
Java.lang.Object
|——Collection
|——List:元素是有序的,元素可以重复,因为该集合体系有索引。
|——ArrayList:底层的数据结构使用的是数组数据结构,查询快增删慢,线程不同步。
|——LinkedList:底层的数据数据结构是链表数据结构,查询慢增删快。
|——Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
|——Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复
|——HashSet:底层数据结构是哈希表。HashSet通过元素的两个方法,hashCode和equals来保证元素的 唯一性。如果元素的hasnCode相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。注意:对于判断元素是否存在以及删除等操作,依赖的方法是元素的hashCode和equals方法。ArrayList依赖的方法只有equals。
|——TreeSet:以对Set集合中的元素进行排序。排序时,当主要条件相同,一定要比较次要条件。底层 数据结构是二叉树,保证元素唯一性的依据是compareTo方法return 0。
|——Map
|——HashMap
|——TreeMap
二、Collection接口
Collection接口是层次结构中的根接口。构成Collection的单位称为元素。Collection接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于List接口与Set接口都继承了Collection接口,因此这些方法对List集合与Set集合是通用的。常用方法如下:
add(E e):将指定的对象添加到集合中;
remove(Object o):将指定的对象从该集合中删除;
isEmpty():返回boolean值,用于判断当前集合是否为空;
iterator():返回在此Collectionn的元素上进行迭代的迭代器,用于遍历集合中的对象;
注意:1.add方法的参数类型是Object,以便于接受任意类型对象。
2.集合中存储的都是对象的引用(地址)。
三、迭代器
获取集合中的元素用迭代器
ArrayList al=new ArrayList();
al.add("java01");
al.add("java02");
Iterator it=al.iterator();
Iterator 是一个接口,接口型引用指向自己的子类对象,而这个子类对象是由集合中的iterator()方法获取的。it.hasNext()方法用来判断集合中是否仍有元素。it.next()方法可以获取集合中的下一个元素。迭代器其实就是集合的取出元素的方式。
由于每一种容器的数据结构不同,所以将取出方式iterator()方法定义在集合的内部。又因为都有判断和取出两个动作,所以将这些共性内容抽取为Iterator接口。
迭代器中不能使用集合的方法进行操作,只能用迭代器自身的方法进行操作。但Iterator只能进行判断取出删除的操作。如果想进行其他操作,如添加修改,就需要使用其子接口:ListIterator。该接口只能通过List集合的listIterator方法获取。
四、List集合
List集合特有的迭代器:ListIterator是Iterator的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素。
1.List接口
List接口继承了Collection接口,因此包含Collection中的所有方法,此外List接口还定义了以下两个非常重要的方法:
get(int index):或得指定索引位置的元素。
set(int index,Object obj):将集合中指定索引位置的对象修改为指定的对象。
2.List接口的实现类
List接口的常用实现类有ArrayList与LinkedList:
ArrayList类实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问;缺点是向指定的索引位置插入对象或删除对象的速度较慢。
ArrayList判断对象是否相同,用的是equals方法,用对象的equals方法和另一个对象比较。自己定义的类继承基类的equals方法,而基类的方法比较的是地址值!因此应该重写equals方法!
List集合判断元素是否相同依据的是元素的Equals方法!
字符串中有自己的equals方法!
LinkedList类采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象,需要向集合中插入删除对象时,使用LinkedList类实现的List集合的效率较高;但对于随机访问集合中的对象,使用LinkedList类实现List集合的效率低。
LinkedList的特有方法:
addFirst();
addLast();
添加元素。
getFirst();
getLast();
获取元素,但不删除元素。
removeFirst();
removeLast();
获取元素,并删除元素。如果集合中没有元素,会出现NoSuchElementException。
在JDK1.6出现了替代方法。
offerFirst();
offerLast();
peekFirst();
peekLast();
获取元素,但不删除元素。如果集合中没有元素,返回null;
pollFirst();
pollLast();
获取元素,并删除元素。如果集合中没有元素,返回null;
五、Set集合
Set集合的功能和Collection的功能是一致的。
Set集合中的对象不按特定的方式排序,只是简单的把对象加入集合中,但Set集合中不能包含重复对象。Set集合由Set接口和Set接口的实现类组成。Set接口继承了Collection接口,因此包含Collection接口中的所有方法。
Set接口常用的两个实现类有HashSet类与TreeSet类。
HashSet通过元素的两个方法,hashCode和equals来保证元素的唯一性。如果元素的hasnCode相同,才会判断equals是否为true。如果元素的hashCode值不同,不会调用equals。
TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口。因此,TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。
Comparable接口强制让实现它的类具备比较性方法为compareTo(T O)。
TreeSet:可以对Set集合中的元素进行排序。排序时,当主要条件相同,一定要比较次要条件。底层数据结构是二叉树,保证元素唯一性的依据是compareTo方法return 0。
往TreeSet里存储的元素必须具有比较性!
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。
TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时就有了比较方式。定义一个类,实现Comparator接口,覆盖compare方法。
定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序方式都存在时,以比较器为主。
六、泛型
泛型: JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制。
好处:
1.将运行时期出现的问题转ClassCastException,移到了编译时期,方便于程序员解决问题,让运行时期问题减少,安全。
2.避免了强制转换的麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用Java提供的对象时,什么时候写泛型:通常在集合框架中很常见,只要见到<>就要定义泛型。
其实<>就是用来接受类型的,当使用集合时,将集合中要存储的数据类型作为参数传递到<>即可。
泛型类:
当类中要操作的引用数据类型不确定的时候,早期定义Object来完成宽展,现在定义泛型来完成扩展。
泛型方法:
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象要明确要操作的具体的类型后,所有要操作的类型就一定固定了。为了让不同的方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
静态方法泛型:
特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
泛型定义方法时,要放在返回类型前面。
泛型限定:用于泛型扩展。
?:通配符,也可以理解为占位符。
<? extends E>:可以接受E类型或者E类型的子类型。上限
<? super E>:可以接受E类型或者E类型的父类型。下限
七、Map
![](https://images2015.cnblogs.com/blog/1135811/201705/1135811-20170513090809176-1341963494.png)
Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
1.添加
put(K key V value)
添加元素:如果添加元素时有相同的键,那么后添加的值会覆盖并返回原有键对应值。
putAll(Map<?extends K,?extends V>m)
2.删除
clear()
remove(Object key)
3.判断
containsKey(Object key)
containsKey(Object value)
isEmpty()
4.获取
get(Object key)
可以通过get方法的返回值来判断一个键是否存在。通过返回null判断。
size()
values()
获取map集合中所有的值
entrySet()
keySet()
Map
|——Hashtable:底层是哈希表数据结构,不可以存入null键和null值。该集合 是线程同步的。JDK1.0,效率低。
|——HashMap:底层是哈希表数据结构,允许使用null键和null值,该集合是不 同步的。JDK1.2,效率高
|——TressMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的 键进行排序。
和Set很像,其实Set底层就是使用了Map集合。
Map 集合的两种取出方式:
1.Set<k> keySet:将map中所有的键存入到Set集合,因为Set集合具备迭代器,所以可以通过迭代方式取出所有的键,然后用get方法获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合,再通过迭代器取出。
2.Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中。而这个关系的数据类型就是Map.Entry。
Map.Entry 其实Entry也是一个接口,它是Map接口中的一个(静态)内部接口。
当数据之间存在着映射关系时,就要先想到map集合。
Map扩展知识:
map集合被使用是因为具备映射关系。
八、其他
1.Collections集合框架的工具类
Collections.sort(list);
Collections.sort(list,new 比较器);
Collections.max(list);
Collections.max(list,new 比较器);
int index=Collections.binarySearch(list,"aaa",new 比较器);
没有查找到返回(-插入点-1)
Collections.fill(list,"pp");
将list集合中的所有元素全部替换成指定元素"pp";
Collections.replaceAll(list,"aaa","pp");
将list集合中所有的"aaa"替换成"pp";
Collections.reverse(list);
翻转list集合中的元素;
Collections.reverseOrder();
返回的是一个比较器;
Collections.reverseOrder(new 比较器);
将已有的比较器逆转;
Collections.SynList(list);
返回指定列表的同步列表
让非同步的集合变成同步集合
Collections.swap(list,1,2);
将集合中角标为1和2的两个元素交换位置
Collections.shuffle(list);
将集合中所有元素重新随机排放
2.Arrays:用于操作数组的工具类。里面都是静态方法。
List<String> list=Arrays.asList(arr):将数组变成list集合
把数组变成list集合的好处:可以使用集合的思想和方法来操作数组中的元素。
注意:将数组变成集合,不可以使用集合中的增删方法,因为数组的长度是固定的。如果增删,会抛出异常。
如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素;如果数组中的元素都是基本数据类型,那么会将该数组,作为集合中的元素存在。
集合转成数组:Collection接口中的toArray方法。
ArrayList<String> al=new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
String[] arr=al.toArray(new String[al.size()]);
指定类型的数组到底要定义多长:当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。当指定类型的数字长度大于了集合的size,就不会新创建数组,而是使用传递进来的数组。所以创建一个刚刚好的数组最优。
将集合变数组是为了限定对元素的操作。
3.高级for循环(foreach语句)
格式:
for(数据类型 变量名:被遍历的集合(Collection)或者数组)
{
}
对集合进行遍历:只能获取元素,但不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。
如果是使用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
传统for循环和高级for循环的区别:
高级for循环有一个局限性,必须有被遍历的目标。
建议在遍历数组的时候还是使用传统for循环,因为传统for循环可以定义角标。
4.可变参数:int...arr
其实就是上一种数组参数的简写形式。不用每次都手动的建立数组对象,只要将要操作的元素作为参数传递即可。隐式的将这些参数封装成了数组。
方法的可变参数在使用时,可变参数一定要定义在参数列表最后面。
5.静态导入
import static java.lang.System.*;导入了System类中所有静态成员。
import static java.util.*;导入的是Arrays这个类中的所有静态成员。
导入后面不跟静态时,导入的都是类。
导入后面跟静态的时候,导入的是某一个类中所有的静态成员。
StaticImport 静态导入:
当类名重名时,需要指定具体的包名。
当方法重名时,需要指定具备所属的对象或者类
转载http://blog.csdn.net/z191726501/article/details/47981355
夫君子之行,静以养身,俭以养德,非淡泊无以明志,非宁静无以致远。