_____集合框架_____
集合框架定义
所谓的集合就是存储数据的容器,而存储方式(数据结构)的多样性导致了集合的多样性,我们针对不同集合的共性不断地向上抽取最终形成的体系我们就称之为集合框架。
常用集合框架图
集合的分类
集合框架分为单列集合的collection和双列集合的map两大类
collection中又分为序列集合list(可以根据位置访问)和不包含重复元素的集合setlist常见的实现子类有ArrayList,Vector,LinkedList:
ArrayList和vector数据结构为数组形式,前者非线程安全后者线程安全
LinkedList数据结构为链表形式,非线程安全
map常见的实现子类有HashMap,HashTable,TreeMap:HashMap和HashTable都是按照哈希值来计算存储位置,所以无序,HashMap线程非安全和允许使用null作为值和键,HashTable线程安全和不允许使用null
TreeMap是按照键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序生成树状存储的
set常见的实现子类有HashSet,TreeSet:
HashSet底层是调用HashMap来实现的,存储时位置是按照哈希值来计算的,所以无序
TreeSet底层是调用TreeMap来实现的,是二叉树状存储,所以有序
List集合系列
特点:
元素是有序的,元素可以重复,因为该集合体系有索引
共性方法:
增:boolean add(E e)
//向列表的尾部添加指定的元素(可选操作)。
void add(int index, E element)
//在列表的指定位置插入指定元素(可选操作)。
boolean addAll(Collection<? extends E> c)
//添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。
boolean addAll(int index, Collection<? extends E> c)
//将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
删:
void clear()
//从列表中移除所有元素(可选操作)。
E remove(int index)
//移除列表中指定位置的元素(可选操作)。
boolean remove(Object o)
//从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
boolean removeAll(Collection<?> c)
//从列表中移除指定 collection 中包含的其所有元素(可选操作)。
改:
E set(int index, E element)
//用指定元素替换列表中指定位置的元素(可选操作)。
查:
E get(int index)
//返回列表中指定位置的元素。
int indexOf(Object o)
//返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
int lastIndexOf(Object o)
//返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
还可以使用迭代器来遍历取得元素:
List list = new ArrayList();
Iterator it = list.iterator();
while(it.hasNext())//判断是否还有下一个元素
{
it.next();//取得下一个元素,指针顺序移动一次
}
此迭代器只能取得元素,不能对元素进行其他操作
于是list集合有了它自己特有的迭代器ListIterator
ListIterator lit = list.listIterator()//返回此列表元素的列表迭代器(按适当顺序)。
list.listIterator(int index)//
此迭代器可以反向遍历:
while(lit.hasPrevious())//判断还有没有前一个元素
{
lit.previous()//取得前一个元素,指针反向移动一次
}
添加:add(E e)//将指定的元素插入列表(可选操作)。
删除:remove()//从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
修改:set(E e)
List实现子类:
ArrayList:
底层数据结构为数组结构,查询速度快,插入删除稍慢,线程不同步(线程不安全)。默认长度为10,长度超过时百分之五十延长。
Vector:
与ArrayList相同,只是线程同步(线程安全)而且数组长度超出时百分之百延长。(已经被ArrayList取代)
LinkedList:
特点:底层数据结构为链表结构,插入删除速度很快,查询速度慢。特有方法:
增:
addFirst(E e)//将指定元素插入此列表的开头。
addLast(E e)//将指定元素添加到此列表的结尾。
删:
removeFirst()//移除并返回此列表的第一个元素。
removeFirstOccurrence(Object o)//从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
removeLast()//移除并返回此列表的最后一个元素。
removeLastOccurrence(Object o)//从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。
查:
getFirst()//返回此列表的第一个元素。
getLast()//返回此列表的最后一个元素。
JDK1.6以后:
原来的删除和查询方法在列表为空时会抛出:NoSuchElementException异常
出现了新的替代方法:
增:
offerFirst(E e)//在此列表的开头插入指定的元素。
offerLast(E e)//在此列表末尾插入指定的元素。
删:
pollFirst()//获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
pollLast()//获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
查:
peekFirst()//获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
peekLast()//获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
Set集合系列
特点:
一个不包含重复元素的 collection。
共性方法:
与Collection一致。
Set实现子类:
HashSet:
底层数据结构是哈希表
判断重复元素的标准:先判断hashCode()的值,不相同再判断equals()的返回值,返回真就算重复元素
判断是否存在和删除等操作都是依赖于这两个方法
TreeSet:
二叉树状存储结构
特点:使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法比较标准:
元素本身具有比较性(优先级低):当其为基本数据类型时,依靠其自然顺序排序;或者让元素实现Comparable接口,覆盖compareTo方法让元素具备自然顺序。
集合本身具有比较性(优先级高):调用构造方法时候传入的比较器Comparator进行排序。
实例:
public class Demo {
public static void main(String[] args) {
//此构造方法传入的比较器的会优先于compareTo方法
/*
TreeSet<Person> tree = new TreeSet<Person>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
return o1.getAge()-o2.getAge();
}
});
*/
//没有比较器会依赖于元素的自然顺序,只能让Person类拥有自然序列,于是需要继承于Comparable接口,重写compareTo方法
TreeSet<Person> tree = new TreeSet<Person>();
tree.add(new Person(18));
tree.add(new Person(19));
tree.add(new Person(18));
System.out.println(tree);
}
}
class Person implements Comparable<Person> {
private int age;
public Person(int age) {
Person.this.age = age;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Person o) {
return 1;
}
@Override
public String toString() {
return "age:"+age;
}
}
Map集合系列
特点:
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
共性方法:
增:V put(K key, V value)
//将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m)
//从指定映射中将所有映射关系复制到此映射中(可选操作)。
删:
void clear()
//从此映射中移除所有映射关系(可选操作)。
V remove(Object key)
//如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
判断:
boolean containsKey(Object key)
//如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
//如果此映射将一个或多个键映射到指定值,则返回 true。
boolean isEmpty()
//如果此映射未包含键-值映射关系,则返回 true。
查:
V get(Object key)
//返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
Set<Map.Entry<K,V>> entrySet()
//返回此映射中包含的映射关系的 Set 视图。
Set<K> keySet()
//返回此映射中包含的键的 Set 视图。
Map实现子类:
HashMap:
底层数据结构是哈希表,可以null键,null值,非线程安全
判断重复元素的标准:先判断hashCode()的值,不相同再判断equals()的返回值,返回真就算重复元素
判断是否存在和删除等操作都是依赖于这两个方法
获取值得的方式:
public class Demo {
public static void main(String[] args) {
HashMap<String, Integer> hm = new HashMap<String, Integer>();
hm.put("lisi", 19);
hm.put("zhangsan", 20);
hm.put("wangwu", 18);
hm.put(null, null);
hm.put(null, null);
//第一种取值方式:通过获取key值集合来取值
Set<String> keySet = hm.keySet();
Iterator<String> iterator = keySet.iterator();
while(iterator.hasNext()) {
String name = iterator.next();
System.out.println("name:"+name+", age:"+hm.get(name));
}
//第二种取值方式:通过获取Entry集合来获取键值对集合
Set<Map.Entry<String, Integer>> entrySet = hm.entrySet();
Iterator<Map.Entry<String, Integer>> iter = entrySet.iterator();
while(iter.hasNext()) {
Map.Entry<String, Integer> entry = iter.next();
System.out.println("key:"+entry.getKey()+", value:"+entry.getValue());
}
}
}
Hashtable:
与HashMap基本相同,不能null键,null值,只是线程同步(线程安全)。(已经被HashMap取代)
TreeMap:
底层是二叉树数据结构,线程非同步,可以根据map集合中的键排序。
特点:使用键的自然顺序对键进行排序,或者根据创建TreeMap时提供的Comparator比较器 进行排序,具体取决于使用的构造方法比较标准:
元素本身具有比较性(优先级低):当其为基本数据类型时,依靠其自然顺序排序;或者让元素实现Comparable接口,覆盖compareTo方法让元素具备自然顺序。
集合本身具有比较性(优先级高):调用构造方法时候传入的比较器Comparator进行排序。
集合工具类
1.Collections的常见方法:
排序:
sort(List<T> list)//根据元素的自然顺序 对指定列表按升序进行排序。sort(List<T> list, Comparator<? super T> c)//根据指定比较器产生的顺序对指定列表进行排序。
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
//我们按照字符串的自然顺序排序
Collections.sort(list);
System.out.println(list);
//我们传入一个与字符串自然顺序相反的比较器来排序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
System.out.println(list);
}
}
/*
结果:
[abc, bca, cba]
[cba, bca, abc]
*/
求最值:
max(Collection<? extends T> coll)//根据元素的自然顺序,返回给定 collection 的最大元素。max(Collection<? extends T> coll, Comparator<? super T> comp)//根据指定比较器产生的顺序,返回给定 collection 的最大元素。
min(Collection<? extends T> coll)//根据元素的自然顺序 返回给定 collection 的最小元素。
min(Collection<? extends T> coll, Comparator<? super T> comp)//根据指定比较器产生的顺序,返回给定 collection 的最小元素。
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
//我们按照字符串的自然顺序取得最大值
String s = Collections.max(list);
System.out.println("max:"+s);
//我们传入一个与字符串自然顺序相反的比较器来获取最大值,也就是正常自然顺序的最小值
s = Collections.max(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
System.out.println("min:"+s);
}
}
/*
结果:
max:cba
min:abc
*/
二分查找:
传入参数就已经表明了只能传入list集合binarySearch(List<? extends Comparable<? super T>> list, T key)//使用二分搜索法搜索指定列表,以获得指定对象。
binarySearch(List<? extends T> list, T key, Comparator<? super T> c)//使用二分搜索法搜索指定列表,以获得指定对象。
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
//使用二分查找前必须保证集合有序,所以先对集合进行排序
Collections.sort(list);
System.out.println(list);
//通过二分查找查询"cba",返回查询到的位置,如果不包含此元素返回负数值,若将此元素插入到此值加1再取反的索引位置,集合仍然有序
int index = Collections.binarySearch(list, "cba");
System.out.println("cba:"+index);
index = Collections.binarySearch(list, "abc");
System.out.println("abc:"+index);
index = Collections.binarySearch(list, "bad");
System.out.println("bad:"+index);
index = Collections.binarySearch(list, "bcd");
System.out.println("bcd:"+index);
}
}
/*
结果:
[abc, bca, cba]
cba:2
abc:0
bad:-2
bcd:-3
*/
替换:
fill(List<? super T> list, T obj)//使用指定元素替换指定列表中的所有元素。replaceAll(List<T> list, T oldVal, T newVal)//使用另一个值替换列表中出现的所有某一指定值。
swap(List<?> list, int i, int j)//在指定列表的指定位置处交换元素。
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
list.add("abc");
System.out.println(list);
//将集合中两个位置的元素互换
Collections.swap(list, 1, 2);
System.out.println(list);
//将集合中所有指定元素替换为另一元素
Collections.replaceAll(list, "abc", "replaceAll");
System.out.println(list);
//将集合中所有元素替换为另一元素
Collections.fill(list, "fill");
System.out.println(list);
}
}
/*
结果:
[abc, cba, bca, abc]
[abc, bca, cba, abc]
[replaceAll, bca, cba, replaceAll]
[fill, fill, fill, fill]
*/
反转:
reverse(List<?> list)//反转指定列表中元素的顺序。public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
System.out.println(list);
//将集合中元素顺序倒置
Collections.reverse(list);
System.out.println(list);
}
}
/*
结果:
[abc, cba, bca]
[bca, cba, abc]
*/
逆转比较器:
reverseOrder()//返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。reverseOrder(Comparator<T> cmp)//返回一个比较器,它强行逆转指定比较器的顺序。
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
//使用正常的排序方法
Collections.sort(list);
System.out.println(list);
//获取与String自然顺序相反的比较器
Comparator<String> comparator = Collections.reverseOrder();
Collections.sort(list, comparator);
System.out.println(list);
//将上面的反序比较器再次取反
comparator = Collections.reverseOrder(comparator);
Collections.sort(list, comparator);
System.out.println(list);
}
}
/*
结果:
[abc, bca, cba]
[cba, bca, abc]
[abc, bca, cba]
*/
线程安全集合创建:
synchronizedCollection(Collection<T> c)//返回指定 collection 支持的同步(线程安全的)collection。synchronizedList(List<T> list)//返回指定列表支持的同步(线程安全的)列表。
synchronizedMap(Map<K,V> m)//返回由指定映射支持的同步(线程安全的)映射。
synchronizedSet(Set<T> s)//返回指定 set 支持的同步(线程安全的)set。
public class Demo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("cba");
list.add("bca");
//此方法返回的集合就是线程安全的,内部只是对原有list的操作方法进行了封装,数据保存不变
List<String> synList = Collections.synchronizedList(list);
System.out.println(synList);
}
}
/*
结果:
[abc, cba, bca]
*/
打乱集合元素:
shuffle(List<?> list)//使用默认随机源对指定列表进行置换。shuffle(List<?> list, Random rnd)//使用指定的随机源对指定列表进行置换。
public class Demo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=1; i<10; i++)
list.add(i);
System.out.println(list);
//打乱集合元素顺序
Collections.shuffle(list);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
}
}
/*
结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[8, 6, 1, 5, 9, 3, 2, 7, 4]
[5, 8, 1, 9, 4, 2, 6, 3, 7]
*/
2.Arrays的常见方法:
二分查找,排序,填充等方法与Collections类似,下面介绍下特有方法转换成集合:
asList(T... a)//返回一个受指定数组支持的固定大小的列表。public class Demo {
public static void main(String[] args) {
int[] in = {1, 2, 3, 4, 5, 6, 7, 8, 9};
Integer[] ins = {1, 2, 3, 4, 5, 6, 7, 8, 9};
//基本数据类型数组会被当成一个object对象,想要使用此方法,基本数据类型必须使用包装类型数组,这是可变参数的一个局限性
//List<int[]> list = Arrays.asList(in);
List<Integer> list = Arrays.asList(ins);
System.out.println(list);
}
}
/*
结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
转换成字符串表现形式:
以int为例:toString(int[] a)public class Demo {
public static void main(String[] args) {
int[] in = {1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println("直接打印数组:"+in);
String str = Arrays.toString(in);
System.out.println("转换成字符串打印"+str);
}
}
/*
结果:
直接打印数组:[I@659e0bfd
转换成字符串打印[1, 2, 3, 4, 5, 6, 7, 8, 9]
*/