第一讲:集合框架
一、集合概述
在程序中可以通过数组来保存多个对象,但在某些情况下无法确定到底需要保存多少个对象,什么类型的对象,此时数组将不适用了。为了保存这些不确定的对象,JDK提供了可以存储任意任意类型的对象,并且长度可变,统称为集合。
二、集合体系
三、集合特点
集合只能存储对象,可以存储不同类型的对象并且集合的长度是可变的。
第二讲:Collection接口
一、Collection接口概述
Collection是单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。Collection:顶层接口
|--->List:元素是有序的(元素存入顺序和取出顺序一致),可以有重复元素,可以有null元素。
|--->Set:元素是无序的(元素存入顺序和取出顺序不一致),元素不可以重复。
二、Collection接口中的常见操作
1、添加元素
add(Objectobj);add方法的参数类型是Object。以便于接收任意类型对象。
2、删除元素
remove(Objectobj);删除元素中指定元素,集合长度会改变。
removeAll(另一集合);删除部分元素,部分元素和另一集合一致。
clear();清空集合。
3、判断元素
contains(Objectobj);判断是否存在obj这个元素
isEmpty();判断是否为空
4、获取个数,集合长度
size();
5、取交集
retainAll(另一集合);调用者只保留两集合的共性元素。
注:集合中存储的都是对象的引用(地址)。
第三讲:List接口
一、概述
List接口继承自Collection接口,是单列集合的一个重要分支,不但继承了Collection接口中的全部方法,而且还增加了一些特有的方法。List集合中允许出现重复的元素,所有的元素都是有序的。二、List特有方法
1、增加
boolean add(index,element);指定位置添加元素
Boolean addAll(index,Collection);在指定位置增加给定集合中的所有元素,若省略位置参数,则在当前集合的后面依次添加元素
2、删除
Boolean remove(index);删除指定位置的元素
3、俢改
set(index,element);修改指定位置的元素。
4、查询
get(index);通过角标获取元素
subList(from,to);获取部分对象元素
三、LinkedList特有方法
1、增加
boolean offFirst();在此列表的开头插入指定的元素。
boolean offLast();在此列表末尾插入指定的元素。
2、获取
peekFirst();获取但不移除此列表的第一个元素;如果此列表为空,则返回null。
peekLast();获取但不移除此列表的最后一个元素;如果此列表为空,则返回null。
3、删除
pollFirst(); 获取并移除此列表的第一个元素;如果此列表为空,则返回null。
pollLast();获取并移除此列表的最后一个元素;如果此列表为空,则返回null。
四、List集合四种遍历方法
//List集合4中遍历方法。
public static void main(String[] args) {
List<Integer> list=new ArrayList<Integer >();//创建ArrayList集合
for(int x=0;x<=5;x++){
list.add(x);//向集合中添加元素
}
System.out.println("--------方法一--------");
Iterator<Integer> it=list.iterator();//Iterator迭代器
while(it.hasNext()){
int num=it.next();
System.out.println(num);
}
System.out.println("--------方法二--------");
for (int i = 0; i < list.size(); i++) {
System.out.println(i);
}
System.out.println("--------方法三--------");
for (Integer num : list) { //foreach循环
System.out.println(num);
}
System.out.println("--------方法四--------");
for(Iterator<Integer>itt=list.iterator();itt.hasNext();){
int num=itt.next();
System.out.println(num);
}
}
}
五、ListIterator接口
在进行list列表元素迭代的时候,如果想要在迭代过程中,想要对元素进行操作的时候,比如满足条件添加新元素,或删除集合中已有的元素。会发生.ConcurrentModificationException并发修改异常。
导致的原因是:
集合引用和迭代器引用在同时操作元素,通过集合获取到对应的迭代器后,在迭代中,进行集合引用的元素添加,迭代器并不知道,所以会出现异常情况。
如何解决呢?
既然是在迭代中对元素进行操作,找迭代器的方法最为合适.可是Iterator中只有hasNext,next,remove方法.通过查阅的它的子接口,ListIterator,发现该列表迭代器接口具备了对元素的增、删、改、查的动作。
程序示例://遍历集合中的元素,当元素为1时就删除。
public static void main(String[] args) {
List<Integer> list=new ArrayList<Integer >();//创建ArrayList集合
list.add(1);//向集合中添加元素
list.add(2);
System.out.println("集合中原有的数据为: "+list);
ListIterator<Integer> it=list.listIterator();//获取ListIterator对象
while(it.hasNext()){
Integer num=it.next();
if(num==1){ //判断元素是否为1
list.remove(num);//删除该集合中的元素
}
}
System.out.println("删除后集合中的数据为: "+list);
}
}
运行结果:
六、ArrayList与linkedList区别
LinkedList:底层数据结构是链表,增删速度快,线程不是同步的。
第四讲:Set接口
一、概述
Set接口继承自Collection接口,与Collection中方法基本一致,Set接口中的元素是无序的,不允许重复。Set主要有两大实现类,分别是HashSet和TreeSet。
二、HashSet
底层数据是哈希表,线程不同步,存取速度快。
HashSet是如何保证数据的唯一性的呢?
通过元素的hashCode方法,和equals方法完成的。当元素的hashCode值相同时,才继续判断元素的equals是否为true。如果为true,那么视为相同元素,不存。如果为false,那么存储。如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
HashSet是如何判断是否是相同元素呢?
HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。
程序示例;
//往HashSet集合中存入Student对象数据,假设ID相同就视为相同数据,不存储。
public static void main(String[] args) {
HashSet<Student> hs=new HashSet<Student>();
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2,"lisi"));
hs.add(new Student(1,"zhangsan"));
Iterator<Student> it=hs.iterator();
while(it.hasNext()){
Student stu=it.next();
System.out.println("学号:"+stu.getId()+"姓名:"+stu.getName());
}
}
}
class Student{
private int id;
private String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student)) //判断对象是否是Student类型数据
throw new RuntimeException("数据错误");
Student p=(Student)obj;
return this.id==p.id&&this.name.equals(p.name); //判断id是否相同
}
public int hashCode()
{
return this.name.hashCode()+this.id;
}
}
三、TreeSet
是Set接口的一个实现类,它内部采用平衡二叉树来存储元素,这样的结构既可以保证TreeSet集合的唯一性,也可以对元素进行排序。
排序原理:排序需要依据元素自身具备的比较性。如果元素不具备比较性,在运行时会发生ClassCastException异常。所以需要元素实现Comparable接口,强制让元素具备比较性,复写compareTo方法。依据compareTo方法的返回值,确定元素在TreeSet数据结构中的位置。
TreeSet方法保证元素唯一性的方式:就是参考比较方法的结果是否为0,如果return 0,视为两个对象重复,不存。
在判断时,需要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。
TreeSet集合排序有两种方式:
1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。
//对HashSet中的数据按照id进行排序,id相同在按照姓名排序。
public static void main(String[] args) {
HashSet<Student> hs=new HashSet<Student>();//创建HashSet集合
hs.add(new Student(3,"wangwu"));//像集合中添加元素
hs.add(new Student(1,"zhangsan"));
hs.add(new Student(2,"lisi"));
Iterator<Student> it=hs.iterator();
while(it.hasNext()){
Student stu=it.next();
System.out.println("学号:"+stu.getId()+"姓名:"+stu.getName());
}
}
}
//创建学生类
class Student implements Comparable<Student>{
private int id;
private String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//重写CompareTo方法
public int compareTo(Student o) {//重写CompareTo方法
if(!(o instanceof Student))//判断传入的数据是否是Student类型
throw new RuntimeException("数据类型错误");
if(this.id==o.id)
return this.name.compareTo(o.name);
return this.id-o.id;
}
}
2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数,
方式较为灵活。
//实现TreeSet集合中字符串按照长度进行排序。
public static void main(String[] args) {
TreeSet<String> set=new TreeSet(new MyComparator());//创建TreeSet对象时传入自定义比较器
set.add("Jordan");
set.add("Kobe");
set.add("Anthony");
Iterator<String> it=set.iterator();
while(it.hasNext()){
String name=it.next();
System.out.println(name);
}
}
}
//定义比较器实现
class MyComparator implements Comparator{
public int compare(Object o1, Object o2) {//实现compare比较方法
String s1=(String)o1;
String s2=(String)o2;
int temp=s1.length()-s2.length();
return temp;
}
}
第五讲:Map接口
一、概述
Map接口是一个双例集合,每一个元素都包含一个键对象Key和键值对Value,它们之间存在一种映射关系。
二、Map集合的子类
Map
|--HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
三、Map集合常用方法
1、添加
void put(K key,V value);添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值。
void putAll(Map <? extends K,? extends V> m);添加一个集合
2、删除
clear();清空
void remove(Object key);删除指定键值对
3、判断
boolean containsKey(Objectkey);判断键是否存在
boolean containsValue(Objectvalue)/;;判断值是否存在
isEmpty(;判断是否为空
4、获取
voidget(Object key);通过键获取对应的值
size();获取集合的长度
Collection<V>value();获取Map集合中所以得值,返回一个Collection集合
四、Map结合取出方式
Map集合的取出原理:将Map集合转成Set集合。再通过迭代器取出。
1.Set<K> keySet():将Map中所以的键存入到Set集合。因为Set具备迭代器。所以可以通过迭代方式取出所以键的值,再通过get方法。获取每一个键对应的值。
<strong> </strong>TreeMap<Integer, String> tm=new TreeMap<>();//创键TreeMap集合
tm.put(1,"qiao");
tm.put(2, "Li");
Set<Integer> keysSet=tm.keySet();//获取键的集合
Iterator<Integer> it=keysSet.iterator();//迭代键的集合
while(it.hasNext()){
Integer key=it.next();
String value=tm.get(key);//获取每个键所对应的值
System.out.println(key+"---"+value);
}
}
}
2.Set<Map.Entry<K,V>>entrySet() ,
返回此映射中包含的映射关系的Set视图,将Map集合中的映射关系存入到Set集合中,
这个映射关系的数据类型是Map.entry,再通过Map.Entry类的方法再要取出关系里面的键和值。
TreeMap<Integer, String> tm=new TreeMap<>();//创键TreeMap集合
tm.put(1,"qiao");
tm.put(2, "Li");
Iterator<Map.Entry<Integer,String>> it=tm.entrySet().iterator();//获取键值对映射关系
while(it.hasNext()){
Entry<Integer, String> me=it.next();
Integer key=me.getKey();//获取键
String value=me.getValue();//获取值
System.out.println(key+"---"+value);
}
}
}
使用集合的技巧总结:
看到Array就是数组结构,有角标,查询速度很快。
看到link就是链表结构:增删速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();
看到hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。
看到tree就是二叉树,就要想到排序,就想要用到比较。
LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。
保证唯一,就用Set。不保证唯一,就用List。