集合框架
集合框架的组成及分类。
集合中会有很多已知实现类,如:ArrayList,HashMap等。为什么会有这么多的类,因为每个类对数据的存储方式不同。存储方式也称为:数据结构。
集合中存储的都是对象的引用(地址)。
Collection接口
一.概述
Collection表示一组对象,这些对象也成为Collection的对象。一些Collection允许有相同的元素,另外一些不允许有相同的元素。一些Collection是有序的,而另外一些是无序的。JDK不提供次接口的任何直接实现,它提供更具体的子接口(如Set,List)实现。
Collection接口
|-List 子接口,元素是有序的,元素可以重复,该集合体系有索引。
|-Set 子接口,元素是无序的,元素不可以重复,该集合体系没有索引。
二.共性方法:
1.添加元素 boolean add(Object obj);
2.删除元素 boolean remove(Object obj);//删除指定元素void
clear();//移除所有元素3.判断元素 boolean contains(Object obj);//判断是否包含obj
boolean isEmpty();//判断是否为空
4.获取长度 int size();//集合中的元素数。
5.取交集元素 boolean retainAll(obj);
三.迭代器:
1.概述:
迭代器就是集合取出元素的方式。 把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素。取出方式就被定义成了内部类。但是每一个容器的数据结构不同,所以取出的方式也不同,取出的动作细节也不同,但是有共性内容判断和取出,将共性内容抽取。所以这些内部类都符合一些规则,这个规则就是迭代器(Iterator)。如何获取集合的取出对象呢?通过一个对外提供的方法:iterator()。
2.方法:hasNext();//判断是否有下一个元素
next();//返回下一个元素
remove();//删除元素
List接口
一.概述
有序的Collection。此接口可以对列表中元素的位置精确定位,用户可以根据索引定位元素。 List集合有索引,所以可以操作角标的方法都是List特有方法。
List接口 元素是有序的,元素可以重复,该集合体系有索引。
|-ArrayList 底层的数据结构使用的是数组结构。特点是:查询速度快,增删稍慢,线程不同步。
|-LinkedList 底层的数据结构使用的是链表数据结构。特点是:增删速度快,查询慢,线程不同步。
|-Vector 底层的数据结构使用的是数组结构。线程同步。效率低,被ArrayList替代。
二.List特有方法
2.删
remove(index);//删除列表中指定位置元素
3.改
set(index,element);
4.查
get(index);
subList(from, to);//包括头,不包括尾
listIterator();//List集合特有的迭代器。
三.ListIterator
List接口提供了特有的迭代器ListIterator。除了允许Iterator接口提供的正常操作外,该迭代器还允许元素插入和替换。
ListIterator特有方法:
add();//添加元素
set();//替换元素
remove();//移除元素
四.LinkedList
特有方法:
1.增
addFirst();将指定元素插入到列表的开头
addLast();将指定元素插入到列表的结尾
2.获取
getFirst();获取列表的第一个元素,如果列表中没有元素,会出现NoSuchElementException异常
getLast();获取列表的最后一个元素,如果列表中没有元素,会出现NoSuchElementException异常
3.删
removeFirst();移除并返回第一个元素,如果列表中没有元素,会出现NoSuchElementException异常
removeLast();移除并返回最后一个元素,如果列表中没有元素,会出现NoSuchElementException异常
JDK1.6出现替代方法:
1.增
offerFirst();
offerLasr();
2.获取
peekFirst();获取列表的第一个元素,如果列表中没有元素,会返回null
peekLast();获取列表的最后一个元素,如果列表中没有元素,会返回null
3.删
pollFirst();移除并返回第一个元素,如果列表中没有元素,会出现返回null
pollLast();移除并返回最后一个元素,如果列表中没有元素,会出现返回null
LinkedList 示例:
/*
* 使用LinkedList模拟一个队列和堆栈数据结构
*/
import java.util.*;
class DuiLie//队列类
{
private LinkedList lk;
DuiLie()
{
lk= new LinkedList();
}
public void myAdd(Object obj)//添加元素
{
lk.addFirst(obj);
}
public Object myGet()//从最后一个开始取出元素
{
return lk.removeLast();
}
public boolean isNull()//判断是否为空
{
return lk.isEmpty();
}
}
class DuiZhan//栈类
{
private LinkedList lk;
DuiZhan()
{
lk=new LinkedList();
}
public void myAdd(Object obj)//添加元素
{
lk.addFirst(obj);
}
public Object myGet()//从第一个开始取出元素
{
return lk.removeFirst();
}
public boolean isNull()
{
return lk.isEmpty();
}
}
public class LinkedListTest
{
public static void main(String[] args)
{
DuiLie();//队列输出
DuiZhan();//栈输出
}
public static void DuiZhan()
{
DuiZhan dz =new DuiZhan ();
dz.myAdd("java 010");
dz.myAdd("java 020");
dz.myAdd("java 030");
dz.myAdd("java 040");
while(!dz.isNull())
{
System.out.println(dz.myGet());
}
}
public static void DuiLie()
{
DuiLie dl= new DuiLie();
dl.myAdd("java 001");
dl.myAdd("java 002");
dl.myAdd("java 003");
dl.myAdd("java 004");
while(!dl.isNull())
{
System.out.println(dl.myGet());
}
}
}
ArrayList 示例:
import java.util.*;
//将自定义对象作为元素存到Arraylist集合中,并删除重复元素
class Person//Person类
{
private String name ;
private int age;
Person(String name ,int age)
{
this.name =name ;
this.age = age;
}
public boolean equals (Object obj)//重写Object类中的equals方法
{
if(!(obj instanceof Person ))
throw new ClassCastException("类型错误");
Person p=(Person )obj;
//System.out.println(this.name+"........"+p.name);
return this.name.equals(p.name) && this.age== (p.age);
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
public class ArrayListTest
{
public static void sop(Object obj)//功能函数
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList ();//创建ArrayList对象
al.add( new Person ("li01",10));//添加元素
al.add( new Person ("li02",20));
al.add( new Person ("li02",20));
al.add( new Person ("li03",30));
// al.add( new Person ("li04",40));
// al.add( new Person ("li04",40));
//System.out.println(al.remove( new Person ("li03",30)));
al=singleElement(al);//功能函数删除相同元素
Iterator it =al.iterator();//迭代器遍历元素
while(it.hasNext())
{
Person p =(Person) it.next();
sop(p.getName()+"-----"+p.getAge());
}
}
public static ArrayList singleElement(ArrayList a)//功能函数删除相同元素,名字年龄相同,即元素相同
{
ArrayList al = new ArrayList ();
Iterator it = a.iterator();//迭代器遍历元素
while(it.hasNext())
{
Object obj = it.next();
if(!al.contains(obj))
{
al.add(obj);
}
}
return al;
}
}
Set接口
一.概述
|-HashSet 底层数据结构是哈希表。HashSet通过hashCode和equals这两个方法保证元素唯一性的。
|-TreeSet 底层数据结构是二叉树。TreeSet通过compareTo方法保证元素唯一性的。
二.HashSet
通过元素的两个方法hashCode()和equals()来完成的,如果元素的hashCode的值相同,才会判断equals是否为true。如果元素的hashCode的值不同,就不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的是hashCode()和equals()方法。
示例:
import java.util.*;
//哈希表存自定义对象
class Person//Person类
{
private String name ;
private int age;
Person(String name ,int age)
{
this.name =name ;
this.age = age;
}
public int hashCode()//重写Object类中的hashCode方法
{
//System.out.println("name:"+this.name);
return this.name.hashCode()+this.age*2;
}
public boolean equals (Object obj)//重写Object类中的equals方法
{
if(!(obj instanceof Person1 ))
throw new ClassCastException("类型错误");
Person p=(Person )obj;
//System.out.println(this.name+"...equals..."+p.name);
return this.name.equals(p.name) && this.age== (p.age);
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
public class HashSetTest
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
HashSet hs = new HashSet();//创建HashSet对象,底层自动调用hashCode()和equals()方法
hs.add( new Person("li01",11));//添加元素
hs.add( new Person("li02",12));
hs.add( new Person("li01",11));
hs.add( new Person("li03",13));
Iterator it = hs.iterator();//迭代器
while(it.hasNext())
{
Person p =(Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}
}
三.TreeSet
底层的数据结构是二叉树。 TreeSet有两种排序方式,第一种是自然排序,使用元素的自然顺序对元素进行排序。第二种是比较器排序,根据创建对象时提供的Comparator排序。线程是不同步的。注意:当主要条件相同时,在比较次要条件。两种方式都存在时,以比较器为主。
元素需要实现Comparable接口,覆盖compareTo方法,这种方法也称为:元素的自然比较,或者默认顺序。
示例:
import java.util.*;
//树表存自定义对象
public class TreeSetTest {
public static void main(String[] args)
{
TreeSet ts = new TreeSet ();//创建TreeSet对象
ts.add(new Student ("java 02",20));//添加元素
ts.add(new Student ("java 03",30));
ts.add( new Student ("java 01",10));
//ts.add(new Student ("java 04",10));
// ts.add(new Student ("java 03",30));
Iterator it = ts .iterator();//迭代器
while(it.hasNext())//判断是否有下一个元素
{
Student s = (Student) it.next();//强转
System.out.println(s.getName()+"......"+s.getAge());
}
}
}
class Student implements Comparable//实现Comparable接口
{
private String name;
private int age;
Student (String name,int age)
{
this.name= name;
this.age =age ;
}
public int getAge()
{
return age;
}
public String getName()
{
return name;
}
public int compareTo(Object obj) //覆盖compareTo方法
{
if(!(obj instanceof Student))
throw new RuntimeException("不是学生");
Student s =(Student)obj;
System.out.println(this.name+"......compare......"+s.name);
if(this.age>s.age)//先比较主要条件
return 1;
if(this.age==s.age)//再比较次要条件
{
return this.name.compareTo(s.name);
}
return -1;
}
}
2.TreeSet排序的第二种方式:当元素自身不具备比较性时,或者是具备的比较性不是所需要的时,这时需要让集合具备比较性。
定义了比较器,将比较器对象作为参数传到TreeSet集合构造函数中。定义一个类,实现Comparator接口,覆盖compare方法。
示例:
import java.util.*;
/*
定义一个学生类,先比较姓名,再比较年龄
*/
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StuCompare());//创建TreeSet对象,传入参数
ts.add(new Student("li01",20));//添加对象
ts.add(new Student("li02",22));
ts.add(new Student("li03",21));
ts.add(new Student("li02",23));
Iterator it = ts.iterator();//迭代器
while(it.hasNext())
{
Student stu = (Student)it.next();
sop("name:"+stu.getName()+",age:"+stu.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
class Student //定义一个学生类
{
private String name;
private int age;
Student (String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class StuCompare implements Comparator//创建类实现Comparator接口
{
public int compare(Object obj1,Object obj2)//覆盖compare方法
{
Student s1 =(Student) obj1;
Student s2 =(Student) obj2;
int num =s1.getName().compareTo(s2.getName());//先比较姓名
if(num==0)
return s1.getAge()-s2.getAge();//姓名相同,再比较年龄
return num;
}
}
Map接口
一.概述
|-HashMap 底层是哈希表数据结构,不可存入null键null值,线程是同步的。不安全一般不用。
|-HashTable 底层是哈希表数据结构,允许存入null键null值,线程是不同步的。效率高。
|-TreeMap 底层是二叉树数据结构,线程是不同步的,可以用于给Map集合中的键排序。
什么时候使用Map集合?
当数据之间存在映射关系,就要想到Map集合。
二.Map集合的常用方
1.添加put(key,value);//如果出现添加相同的键,后添加的值会覆盖原有的键以及对应的值,并且put方法会返回被覆盖的值。
putAll(Map<? extends K ,? extends V> m);
2.删除
remove(key);//删除指定键以及对应的值
isEmpty();//判断是否为空
4.获取
entrySet(); //Map两种取出方式
ketSet();
三.Map集合的两种取出方式
Map集合取出原理:先将Map集合转成Set集合,再通过迭代器取出
将Map集合中所有的键存到Set集合中,因为Set集合具备迭代器,取出Set集合中的键,通过Map集合的get(key)方法获取键对应的值。
示例:
import java.util.*;
//map集合的取出方式.keySet方法
public class HashMapTest1
{
public static void main(String[] args)
{
Map
map = new HashMap
();//创建Map
的对象
map.put("001", "jj");//添加元素
map.put("002", "hh");
map.put("007", " jb");
map.put("004", "kk");
Set
keySet = map.keySet();//keySet的取出方式
Iterator
it = keySet.iterator();//迭代器 while(it.hasNext()) { String str= it.next();//获取键 String col =map.get(str);//获取值 sop("key:"+str+",value:"+col); } } public static void sop(Object obj) { System.out.println(obj); } }
2 .Set<Map.Entry<k,v>> entrySet
将Map集合中所有的键存到Set集合中,取出Set集合中的键,键的数据类型是Map.Entry。通过Map集合的gatValue()和getKey()方法获取值。
import java.util.*;
import java.util.Map.Entry;
//Map的entrySet取出方式
public class HashMapTest2
{
public static void main(String[] args)
{
Map
map= new HashMap
();//创建Map集合的对象。
map.put("003", "a3");//添加元素
map.put("002", "a2");
map.put("001", "a1");
map.put("004", "a4");
Set
> entrySet = map.entrySet();//entrySet取出方式
Iterator
> it =entrySet.iterator();//迭代器 while(it.hasNext()) { Map.Entry
mm=it.next(); String key= mm.getKey(); //获取键 String value = mm.getValue(); //获取值 sop("key:"+key+",value:"+value); } } public static void sop(Object obj) { System.out.println(obj); } }
综合示例:
import java.util.*;
import java.util.Map.Entry;
/*1.描述学生。学生属性 :姓名,年龄
2. 定义map容器,将学生作为键,地址作为值,存入
3.获取map容器的元素
*/
public class TreeTest_1
{
public static void main(String[] args)
{
//创建TreeMap对象,传进参数
TreeMap
tm = new TreeMap
( new StuCom());
tm.put(new Student("za1",25) , "beijing");//添加对象
tm.put(new Student("za2",28) , "tianjin");
tm.put(new Student("za4",21) , "shanghai");
tm.put(new Student("za3",25) , "wuhan");
tm.put(new Student("za1",25) , "dfgdgdfgdgfdgdgdfgf");
//method 1 keySet
Set
keySet = tm.keySet();//用keySet方法将map存到Set集合中
Iterator
it1 = keySet.iterator ();//迭代器方法
while(it1.hasNext())
{
Student s1 =it1.next();//获取值
String str1=tm.get(s1);
sop(s1+"......"+str1);
}
//method2 entrySet
Set
> entrySet = tm.entrySet();//用entrysetSet方法将map存到Set集合中 Iterator
> it2 = entrySet.iterator(); while(it2.hasNext()) { Map.Entry
me = it2.next(); Student s2= me.getKey();//获取键 String str2 =me.getValue();//获取值 sop(s2+":::::"+str2); } } public static void sop(Object obj) { System.out.println(obj); } } class Student implements Comparable
//学生类实现Comparable接口 { private String name ; private int age; Student (String name ,int age ) { this.name =name ; this.age = age ; } public int hashCode()//覆盖Object中hashCode方法,为了让元素适应哈希表结构 { return name.hashCode()+age*77; } public boolean equals (Object obj)//覆盖Object中equals方法 { if(!(obj instanceof Student)) throw new ClassCastException("ClassCastException"); Student s1 = (Student)obj; return this.name.equals(s1.name) && this.age==s1.age; } public String getName () { return name ; } public int getAge () { return age; } public String toString () { return name+",..."+age; } public int compareTo(Student o)//覆盖Comparable接口中的compareTo方法 { int num= this.name.compareTo(o.name); if(num==0) return new Integer (this.age).compareTo(new Integer (o.age)); return num; } } class StuCom implements Comparator
//覆盖Comparator接口中compare方法,先比较年龄,再比较姓名 { public int compare (Student s1 ,Student s2) { int num= new Integer ( s1.getAge()).compareTo( new Integer (s2.getAge())); if(num==0) return s1.getName() .compareTo( s2.getName()); return num; } }
四.Map应用
1. 示例:import java.util.*;
import java.util.Map.Entry;
/*"sdadadasfsdfg"字母出现的次数
* 打印结果:a(2)b(1)
* 思路:
* 1.将字符串 变成字符数组
* 2.用字母作为键去找集合中的次数,
* 如果次数为null,就把字母和1加入集合中。
* 如果次数不为null,次数++,再把字母和次数加入集合中
* 3.取出存到缓冲区
* 4.在取出
*/
public class TreeMapTest_1
{
public static void main(String[] args)
{
String str=charCount("asdasfgsd");//调用函数
System.out.println(str);
}
public static String charCount(String s)
{
char[] arr=s.toCharArray();//转换成字符数组
//创建TreeMap对象
TreeMap
map = new TreeMap
();
for(int x= 0; x
> entrySet = map.entrySet();//map的entrySet方法存到Set中
Iterator
> it =entrySet.iterator ();//迭代器 while(it.hasNext()) { Map.Entry
me = it.next(); Character ch = me .getKey();//获取键 Integer in = me .getValue();//获取值 sb.append(ch+"("+in+")"); } return sb.toString(); } }
2.示例
import java.util.*;
public class MapDemo_1
{
public static void main(String[] args)
{
/*jiuyeban "01" "zhangsan"
* jiuyeban "02" "wanglei"
* yureban "01" "guangguang"
* yureban "02" "guoxi"
*/
//有三者相关联的情况
/*
//定义学校
HashMap
> xuexiao= new HashMap
>();
//jiuyeban
HashMap
jiuye= new HashMap
();
//yureban
HashMap
yure = new HashMap
(); //学校添加教室 xuexiao.put("jiuyeban", jiuye); xuexiao.put("yureban", yure); //教室里有学生 jiuye.put("01","zhangsan" ); jiuye.put("02","wanglei" ); yure.put("03","guangguang" ); yure.put("04","guoxi" ); //遍历教室 Iterator
it = xuexiao.keySet().iterator(); while(it .hasNext()) { String room= it.next(); HashMap
jiaoshi= xuexiao.get(room); System.out.println(room); getStudentInfo(jiaoshi);//得到教室里面的学生信息 }*/ // methodStu(); } public static void getStudentInfo(HashMap
roomMap)//得到教室里面的学生信息 { Iterator
it = roomMap.keySet().iterator(); while(it.hasNext()) { String id=it.next(); String name=roomMap.get(id); System.out.println(id+".........."+name); } } public static void methodStu() { /*jiuyeban new Student("01" "zhangsan") * jiuyeban new Student("02" "wanglei") * yureban new Student("01" "guangguang") * yureban new Student("02" "guoxi") */ //两者之间有关联的情况 HashMap
> xuexiao= new HashMap
>(); //jiuyeban List jiuye = new ArrayList(); //yureban List yure= new ArrayList(); //学校添加教室 xuexiao.put("jiuyeban", jiuye); xuexiao.put("yureban", yure); //教室里有学生 jiuye.add( new Student("01","zhangsan") ); jiuye.add( new Student("02","wanglei") ); yure.add( new Student("03","guangguang") ); yure.add( new Student("04","guoxi" )); Iterator
it = xuexiao.keySet().iterator();//迭代器 while(it.hasNext()) { String room = it.next(); List
li=xuexiao.get(room); System.out.println(room); getInfo(li);//迭代器 } } public static void getInfo(List
room) { Iterator
it = room.iterator(); while(it.hasNext()) { Student s= it.next(); System.out.println(s); } } } class Student //学生类 { private String name ; private String id; Student (String name ,String id) { this.name = name ; this.id= id; } public String toString() { return id+":::"+name; } }
其他
Collections:用于操作集合的工具类
Arrays:用于操作数组的工具类
static <T> List <T> aslist() 将数组变成集合
把数组变成集合有什么好处?
可以使用集合的思想和方法操作数组中的元素。
注意:将数组变成集合,不可以使用集合的增删操作,因为数组是固定长度的。
如果数组中的元素是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素是基本数据类型,变成集合时,数组就作为集合的元素存在。
集合变数组
指定类型的数组长度到底要定义多长呢?
当指定类型的数组长度小于集合的size时,该方法内部会自动创建一个新的数组,长度为集合的size。当指定类型的数组长度大于集合的size是,不会创建数组了,使用传递进来的数组。所以要创建一个刚刚好的数组最优。
为什么将集合变成数组?
为了限定对元素的操作,不能进行增删了。