java 集合框架
----------android培训、java培训、java学习型技术博客、期待与您交流!------------
集合类
为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储, 集合就是存储对象最常用的一种方式。 数组和集合类同是容器,有何不同? 数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集 合只能存储对象。而数组里存的都是指定类型的元素,而集合中可存放不同类型的对象。
集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象,另外集合中存放的都是对 象地址值,而不是对象实体。
集合框架 因为集合类是存储对象的,但是在存储的过程中发现有些存储对象的集合类存在一些共性的东西,于是就 向上提取,在不断提取的过程中就形成了一个体系
一、集合框架的构成及分类
(一)集合框架
因为集合类是存储对象的,但是在存储的过程中发现有些存储对象的集合类存在一些共性的东西,于是就向上提取,在不断提取的过程中就形成了一个体系。
体系的共性方法:
首先它是一个集合,也就是容器,既然是容器那就像数组似的,基本上对容器里的操作会有增上改吧。
Collection是一个接口,定义了存储一组数据的方法,包含了List和Set,是ArrayList,LinkedList,Vector,HashSet,TreeSet等向上提取得到的,有它们几个的共性,Collection是java集合类的基础。
Collection定义了集合框架的共性功能。
1,添加
boolean add(e);确保此 collection 包含指定的元素。就是看是否添加成功,返回值类型是布尔型
boolean addAll(collection);将指定 collection 中的所有元素都添加到此 collection 中。
2,删除
boolean remove(e);如果存在的话就从此 collection 中移除指定元素的单个实例,
boolean removeAll(collection);
void clear(); 移除此 collection 中的所有元素(可选操作)。
3,判断。
boolean contains(e);如果此 collection 包含指定的元素,则返回 true。
boolean isEmpty();如果此 collection 不包含元素,则返回 true。
4,获取
Iterator iterator(); 返回在此 collection 的元素上进行迭代的迭代器。
int size();返回此 collection 中的元素数
5,获取交集。
boolean retainAll();仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
6,集合变数组。
Object[] toArray();返回包含此 collection 中所有元素的数组。
添加的时候要注意的问题:
1,add方法的参数类型是Object。以便于接收任意类型对象。
2,集合中存储的都是对象的引用(地址)
部分代码:
//创建一个集合容器。使用Collection接口的子类。ArrayList
ArrayList al = new ArrayList();
//1,添加元素。
al.add("java01");//add(Object obj);
//2,获取个数。集合长度。
sop("size:"+al.size());
//3,删除元素。
al.remove("java02");
al.clear();//清空集合。
//4,判断元素。
sop("java03是否存在:"+al.contains("java03"));
sop("集合是否为空?"+al.isEmpty());
迭代器:
什么是迭代器呢?
其实就是集合的取出元素的方式。会直接访问集合中的元素。因为集合中每种元素的数据
结构不同,所以取出方式也不同,所以迭代器iterator以内部类的方式定义在了集合内部,
但是定义在了内部用的时候怎么用这个内部类的对象啊,所以java就提供了iterator()的
方法来返回个迭代器对象,就是那个集合调用这个方法就返回哪个集合的迭代器,这样不
管是哪种集合不就都能取里面的对象啦。
部分代码:
ArrayList a = new ArrayList();
a.add("java01");
a.add("java02");
a.add("java03");
a.add("java04");
sop(a);
//Iterator it = a.iterator();//获取迭代器,用于去处集合中元素
for(Iterator it = a.iterator();it.hasNext();)//比较节约内存
{
sop(it.next());
}
connection
(二)--List 元素是有序的,可以重复的
--ArrayList:底层的数据结构是数组型结构,不同步。特点 查询速度快 增删速度稍慢,因为每
增减一个后面的元素都要向前或向后顺延。
--LinkedList:底层结构是链表数据结构
--Vector:
--set 元素是无序的 不可以重复的
--hashSet:底层是哈希表结构
--TreeSet:可以对Set集合里的元素进行排序
List:
凡是可以操作角标的方法都是该体系特有的方法
增
add(index,element)指定位置添加元素
add(index,Collection)指定位置添加整个集合元素
删
remove(index)
改
set(index,element)
查
get(index)
subList(from.to)//获取子列表
int indexOf(obj) 获取指定元素的位置 返回的是int型
listIterator()//List特有的方法 Iterator只能判断是否有元素,取出和移除元素
List集合特有的迭代器,ListIterator是Iterator的子接口
在迭代时,不可以通过集合对象的方法来操作集合中的元素,因为会发生并发修改异常,
所以呢在迭代时只能用迭代器的方法操作元素,可是Iterator的方法是有限的,只能
对元素进行判断,取出和删除的操作
如果想要其他的操作,如添加,修改等就需要使用其子接口。
该接口只能通过List集合的listIterator的方法获取,如:
部分代码:
import java.util.*;
class ListDemo
{
public static void listIteratorDemo()
{
//演示迭代器
ArrayList a = new ArrayList();
//添加元素
a.add("java01");
a.add("java02");
a.add("java03");
//在迭代过程中,添加或删除元素
ListIterator it = a.listIterator();
while(it.hasNext())
{
Object obj = it.next();
if(obj.equals("java02"))
it.add("java007");
if(obj.equals("java03"))
it.set("java008");
//sop(obj);
}
sop(it.hasPrevious());//从后遍历
sop(a);
while(it.hasPrevious())
{
sop(it.previous());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
LinkedList特有方法:
addFirst()
在JDK1.6以后后被offerFirst(),offerLast()取代
addLast()
getFirst()
get获取元素但不删除,如果集合里面没元素会抛出“没有这个元素”异常
getLast()
在JDK1.6以后后被peekFirst(),peekLast()取代,如果集合里面没元素会返回null
removeFirst()
remove也能获取元素,但是也删除元素如果集合里面没元素会抛出“没有这个元素”异常
removeLast()
在JDK1.6以后后被pollFirst(),pollLast()取代,如果集合里面没元素会返回null
部分代码:
class LinkedListDemo
{
public static void main(String[] args)
{
LinkedList link = new LinkedList();
link.addFirst("java01");
link.addFirst("java02");
link.addFirst("java03");
link.addFirst("java04");
sop(link);
while(!link.isEmpty())
{
sop(link.removeLast());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
枚举就是Vector特有的取出方式
发现枚举和迭代很像,其实枚举和迭代是一样的,因为枚举的名称和方法的名称都过长,所以被迭
代器取代了,枚举就郁郁而终了
Vector有三种取出方式,枚举,迭代,for循环遍历(get()方法)
*/
class VectorDemo
{
public static void main(String[] args)
{
Vector v = new Vector();
v.add("java01");
v.add("java02");
v.add("java03");
v.add("java04");
sop(v);
Iterator it = v.iterator();
while(it.hasNext())
{
sop(it.next());
}
sop(v);
//枚举方法
Enumeration e = v.elements();
while(e.hasMoreElements())
{
sop(e.nextElement());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
(三)--set 元素是无序的 不可以重复的
--HashSet:底层是哈希表结构
HashSet是如何保证元素的唯一性的呢?
是通过元素的equals()和hashCode()两个方法来完成的
如果元素的哈希值相同才会判断equals()是否为true
如果元素的哈希值不同则不会调用equals();
注意:对于判断元素是否存在以及删除等操作以来的方法都是equals()和hashCode()
--TreeSet
可以对Set集合里的元素进行排序
import java.util.*;
class HashSetDemo
{
public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add("java01");
hs.add("java02");
hs.add("java03");
hs.add("java04");
sop(hs);//打印出来是无序的
sop(hs.add("java05"));//因为HashSet集合里面是无序的不可重复的,所以hs.add()返回的是boolean型
sop(hs);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
--HashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。
--TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。
保证元素唯一性的依据:compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,
覆盖compareTo方法。也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自
身具备比较性。在集合初始化时,就有了比较方式。
TreeSet:底层数据结构是二叉树。可以对存进里面的元素进行排序,排序的前提是元素本身要具有比较性
TreeSet练习部分代码:
import java.util.*;
class Student implements Comparable//元素本身要具备比较性,所以要实现comparTo方法
{
private String name;
private int age;
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
Student(String name,int age)
{
this.name = name;
this.age =age;
}
public int compareTo(Object obj)//实现comparable接口,覆盖此方法
{
//System.out.println(this.age+"compaterTo"+s.age);
if(!(obj instanceof Student)) //如果传进来的参数不指向student类(多态)则抛异常
throw new RuntimeException("传入的不是学生对象");
Student s = (Student)obj; // 向下转型
System.out.println(this.age+"compaterTo"+s.age);
if(this.age
return -1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);//这一句用的是字符串默认的排序方式,
}
else
return 1;
}
}
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02",20));
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi01",23));
ts.add(new Student("lisi002",20));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student s = (Student)it.next();
System.out.println(s.getName() +"..."+s.getAge());
}
System.out.println(ts);
}
}
(四)泛型:JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。
好处:把运行时期出现的ClassCastException,转移到了编译时期,
方便于程序员解决问题,让运行时 问题减少,安全。
避免了强制转换的麻烦。
泛型格式:通过<>定义需要操作的引用数据类型
在使用java提供的对象时,什么时候使用泛型呢?
通常在集合框架中很常见只要见到<>就要定义泛型,其实<>就是用来接受泛型的
当时用集合时,将集合中需要存储的数据类型作为参数传递到<>中即可。
部分代码:
class GenericDemo
{
public static void main(String[] args)
{
ArrayList al = new ArrayList();//说明这个集合里面只能放String类型的元素。
al.add("java01");
al.add("java03");
al.add("javasa03");
//al.add(6);集合里面只能装引用对象不能装变量。
//al.add(3);类型转换异常,这个集合里面有两种类型的对象
Iterator it = al.iterator();
while(it.hasNext())
{
//String s= (String)it.next();
String s= it.next();//避免了强制转换,因为既然上面定义了String泛型,说明集合
//里面装的都是String也就可以不用强制转换了
System.out.println(s+"::"+s.length());
}
}
}
泛型类
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象
明确要操作的具体类型后,所有要操作的类型就已经固定了。
泛型方法
为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。
特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
部分代码:
class Demo
{
public void show(T t)
{
System.out.println("show:"+t);
}
public void print(Q q)
{
System.out.println("print:"+q);
}
public static void method(W t)
{
System.out.println("method:"+t);
}
}
class GenericDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
d.show("haha");
//d.show(4);
d.print(5);
d.print("hehe");
Demo.method("hahahahha");
}
}
(五)Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
Map里的key集存储方式和对应的Set集合中的元素存储方式一致;
学生都有一个学号,我们能点学号就能找到某个学生,好比这个学号就是key,学生就是value。
Map.Entry是Map接口的内部接口,专门用来保存key-value内容:
Map常用方法
void clear():删除该Map对象中所有的key-value对。也就是清理该集合;
boolean containsKey(Object key):查询Map中是否包含指定的key;
boolean containsValue(Object value):查询Map中是否包含至少一个value;
Set entrySet():返回Map所包含的key-value对所组成的Set集合,每个集合元素都是Map.Entry对象(Entry是Map内部类);
Object get(Object key):返回指定key所对应的value,若此Map中不包含该key,返回null;
boolean isEmpty():判断Map集合是否为空;
Set keySet():返回该Map中所有key所组成的Set集合;
Object put(Object key,Object value):添加一个key-value对,若Map中已有与key相等的key-value对,则新的key-value对覆盖原来的key-value对;
void putAll(Map m):将m中的key-value赋值到调用该方法的Map对象中;
Object remove(Object key):删除指定key所对应的key-value对,返回本删除key所关联的value,若key不存在,返回null;
int size():返回该Map里面key-value对的个数;
Collection values():返回Map里所有value组成的Collection。
Map集合的输出
按照最正统的做法,所有的Map集合的内容都要依靠Iterator输出,以上虽然是完成了输出,但是完成的不标准,Map集合本身并不能直接为Iterator实例化,如果此时非要使用Iterator输出Map集合中内容的话,则要采用如下的步骤:
方法一:
1.通过entrySet方法变成Set对象
2.调用Set的Iterator方法,此时每个Iterator对象是Map.Entry对象
3.对Map.Entry分离出 key - value
方法二:
1.通过keySet得到Map集合多有key的Set集合
2.调用Set的Iterator方法,此时每个Iterator对象是key值
3.通过Map的getValue(key)得到value值
实例1
package com.collecion;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapTest {
public static void main(String[] args) {
Mapmm = new HashMap();
mm.put(new studente("lisi", 22), "beijing");
mm.put(new studente("liwu", 23), "tianjing");
mm.put(new studente("liliu", 56), "shanghai");
//第一种取法
Setst = mm.keySet();
Iteratorit = st.iterator();
while(it.hasNext()){
studente stu = it.next();
String addr =mm.get(stu);
System.out.println(stu.getName()+".."+stu.getAge()+".."+addr);
}
//第二种取法
Set sts =mm.entrySet();
Iterator ite = sts.iterator();
while(ite.hasNext()){
Map.EntrymEntry =ite.next();
studente keyStudent =mEntry.getKey();
String valueString = mEntry.getValue();
System.out.println(keyStudent.getName()+".."+keyStudent.getAge()+".."+valueString);
}
}
}
class studente implements Comparable{
private String name;
private int age;
studente(String name ,int age ){
this.name=name;
this.age=age;
}
public int compareTo(studente ss) {
int num = new Integer(this.age).compareTo(new Integer(ss.age));
if(num ==0)
return this.name.compareTo(ss.name);
return num;
}
@Override
public int hashCode() {
return name.hashCode()+age*34;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof studente))
throw new ClassCastException("匹配异常");
studente s= (studente) obj;
return this.name.equals(s.name)&&this.age ==s.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;
}
}
实例2
练习要求“abcdabcdfghhdd”获取该字符串的字母楚翔的次数希望打印的结果为a(2)b(2)....
* 思路: 1、因为要对每一个字母操作所以将字符串转换成字符数组。
* 2、每一个字母都有对应的次数说明字母和次数之间都有映射关系选用Map集合。
* 3、因为打印结果又顺序选用TreeMao集合
* 4、遍历数组,将每个字母作为键去查找map集合如果返回null,将字母和1存入到集合中。如果返回不是null
* 说明该字母在集合中已经存在并有对应的次数,那么就获取该次数并进行自增,然后将字母和自增后的次数存入到
* map集合中覆盖掉原键对应的值。
* 5、将map集合中的数据变成指定的字符串形似返回。
package com.collecion;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class MapTest3 {
public static void main(String[] args) {
String ss ="abcdabcdfghhdd";
String s = charCount(ss);
System.out.println(s);
}
private static String charCount(String st) {
char[] ch = st.toCharArray();
Maptm = new TreeMap();
int count = 0;
for (int x = 0; x < ch.length; x++) {
if (!(ch[x] >='a'&&ch[x]<='z'
ch[x] >='A'&&ch[x]<='Z'))
continue;
Integer value = tm.get(ch[x]);
if(value!=null)
count = value;
count++;
tm.put(ch[x], count);
count=0;
}
StringBuilder sd = new StringBuilder();
Set se = tm.entrySet();
Iterator< Map.Entry> it = se.iterator();
while (it.hasNext()){
Map.Entryme = it.next();
Character ca = me.getKey();
Integer in = me.getValue();
sd.append(ca +"["+in+"]");
}
return sd.toString();
}
}
(六)Collections类
操作集合的工具类:
static void reverse(List list):反转指定List集合中的顺序;(和ListItertor的逆序排列一样!)
static void shuffle(List list):对集合元素随机排序
static void sort(List list):自然升序排序
static vois swap(List list,int i, int j):将指定的List集合i处元素和j处元素进行交换;
static void rotate(List list, int distance):
若distance为正数,将list集合后的distance个元素移到前面;
当distance为负数,将list集合前的distance个元素移到后面;
static int binarySearch(List list, Object key) 使用二分搜索法搜索指定列表,以获得指定对象。
调用之前 必须调用 Collections.sort(List list)(完成自然排序);
static Object max(Collection coll) 根据元素的自然顺序,返回给定 collection 的最大元素。
static Object min(Collection coll) 根据元素的自然顺序,返回给定 collection 的最小元素。
static void fill(List list, Object obj) 使用指定元素替换指定列表中的所有元素。
static int frequency(Collection c, Object o) 返回指定 collection 中等于指定对象的元素数。
static int indexOfSubList(Listsource, List target) 返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。
static int lastIndexOfSubList(List source, List target) 返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。
static boolean replaceAll(List list, Object oldVal, Object newVal) 使用另一个值替换列表中出现的所有某一指定值。
(七)Arrays
public static List asList(Object... a)返回一个受指定数组支持的固定大小的列表(返回的是不可变的List(长度固定))。数组转换成集合
Collection.toArray() 将集合转换成数组