第一章、Collection集合
1.1、集合概述
(1)集合:集合是Java中提供的一种容器,可以用来存储多个数据。
(2)集合与数组的区别:
①数组长度固定,集合长度可变。
②数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象,而且对象的类型可以不一样。在开发中一般对象多的时候,使用集合进行存储。
1.2、Collection集合框架
(1)集合按照存储节后可以分为两大类,分别是单列集合Java.util.Collection和双列集合Java.util.Map。
(2)框架解释
Collection(最顶层):单列集合类的根接口,用于存储一系列符合某种规则的元素。(没有带索引的方法)
最顶层:Collection接口
继承自顶层:List接口、Set接口
实现类:
List(Vector类、ArrayList类、LinkedList类)
Set(TreeSet类、HashSet类、LinkedHashSet类)
List(继承自顶层):Java.util.List,存取有序、允许存取重复元素、有索引。
Set(继承自顶层):Java.util.Set,存取无序(实现类LinkedHashList特殊,可以保护数据存取顺序)、不允许存储重复元素、无索引。
(3)底层实现
HashSet:底层是哈希表+红黑树实现的。
LinkedHashSet:底层是哈希表+链表实现。
TreeSet:底层是二叉树实现,多用于排序。
1.3、Collection常用方法
public boolean add(E e){}; //向集合添加元素
public boolean remove(E e){}; //删除集合中的某个元素
public void clear(){}; //清空集合所有的元素
public boolean contains(E e){};//判断集合是否包含某个元素
public boolean IsEmpty(){}; //判断集合是否为空
public int size(){}; //获取集合长度
public Object[] toArray(){}; //将集合转成一个数组
public static <T> boolean addAll(Collection<T>,T...element){}; //向集合内添加一些元素
public static void shuffle(List<?> list){}; //打乱集合的顺序
public static <T> void sort(List<T> list){}; //将集合以默认顺序排列(一般升序)
public static <T> void sort(List<T> list,Comparator<? super T>) //将集合中元素按照制定规则排序
1.3.1、可变参数
方法列表通数据类型形数有多个实参。
(1)声明:
修饰符 返回值类型 方法名(数据类型...变量名){};
public class Demo{
public static void main(){String[] args}(
int i = add(10,20,30,40,50);
)
public static int add(int...arr){
普通for循环
/*
int sum;
for(int i=0,i<arr.length(),i++){
sum +=arr[i];
return sum;
}
*/
//增强for循环
for(int i:arr){
sum += i;
return sum;
}
}
}
(2)底层原理
可变参数底层实际是一个数组,根据传入参数的个数创建相应长度的数组,可以没有,也可以很多。
(3)注意事项
一个方法参数列表只能有一个可变参数。
如果方法有多个参数,可变参数必须是最后一个。
(4)可变参数的特殊写法
public static void method(Object...o){};
1.3.2、sort方法
使用前提:被排序的集合里面被存储的元素必须实现Comparable接口,重写接口方法中的compareTo定义排序的规则。
public int compareTo(Person o){
return this.getAge() - 0 .getAge();//自己-参数=升序,参数-自己=降序
}
1.4、List接口
特点:有序(存储与取出顺序相同)、有索引、允许存储重复元素
遍历集合:for循环、增强for循环、迭代器
API位置:Java.util.List
1.4.1、ArrayList集合
底层实现:底层是数组实现,查询快,增删慢。
(1)常用方法
未记录特殊方法。
1.4.2、LinkedList集合
底层实现:底层是链表实现,查询慢,增删快。
API位置:Java.util.ListedList
(1)常用方法
!(https://img-blog.csdnimg.cn/423c0ada72cf4bc6818a6ae286299cc0.png)
1.4.3、Vector集合
底层实现:底层是数组实现,查询快,增删慢。
API位置:Java.util.Vactor
(1)常用方法
未记录特殊方法。
1.5、Set接口
特点:不允许存储重复元素、无索引、无序集合
遍历集合:迭代器
API位置:Java.util.Set
1.5.1、哈希表
(1)哈希值
哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是实际存储的物理地址)
在Object类中有一个可以获取对象hash值的方法。
public native int hashCode();
native:代表该方法调用的是本地操作系统的方法。
PS:一般的线性表,树中,记录在结构中的相对位置是随机的,即和记录的关键字之间不存在确定的关系,因此,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在“比较“的基础上,查找的效率依赖于查找过程中所进行的比较次数。 理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。
哈希表中元素是由哈希函数确定的。将数据元素的关键字K作为自变量,通过一定的函数关系(称为哈希函数),计算出的值,即为该元素的存储地址。
(2)哈希表
JDK1.8版本之前,哈希表=数组+链表
JDK1.8版本之后,哈希表=数组+链表
哈希表=数组+红黑树(提高查询速度)
(3)Set集合不能存储重复元素的原因。
(4)Set中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中元素对象的唯一。
1.5.2、HashSet集合
底层实现:底层是哈希表结构,查询速度非常快。
API位置:Java.util.HashSet
(1)常用方法
未记录特殊方法。
1.5.3、LinkedHashSet集合
底层实现:哈希表(数组+链表/红黑树)+链表:(多了一条链表,记录元素的存储顺序,保证元素有序。
第二章、Iterator(迭代器)
Java.util.Iterator接口
通用取出集合元素的方式,在取出元素之前,先要判断是否存在这个元素,如果有就把这个元素取出,继续哦按段,如果还有就再取出来,一直把集合中的所有元素全部取出,这种取出方式专业术语叫做“迭代器”。
Iterator是接口,无法直接使用,需要使用Iterator的实现类对象。获取实现类对象的方式比较特殊。Collection接口中有一个方法,叫iterator(),这个方法返回的就是迭代器的实现对象。
2.1、常用方法
Boolean hasNext()//集合中仍有元素,则返回ture
E next() //返回迭代的下一个元素
Interator<E> Iterator()//返回再次collection的元素上进行迭代的迭代器。
2.2、迭代器使用与实现
(1)迭代器的使用步骤
①使用集合中的方法iterator()获取迭代器的实现类
②使用Iteratoro接口中的方法hasNext判断还有无下一个元素
③使用Iterator接口中的方法next取出集合中的下一个元素
(2)迭代器的代码实现
public class Demo{
public static void main(String[] args){
//创建一个元素
Collection<Sting> coll = new ArrayList<>();
coll.add("姚明");
coll.add("科比");
coll.add("麦迪");
coll.add("詹姆斯");
coll.add("艾弗森");
//使用while写迭代器
Iterator<String> id = coll.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//使用for循环写迭代器
//Iterator接口的使用是通过一种迂回的方式去实现的,通过集合对象调用Collection内的Iterator方法,将处理过后的对象实体返回给Iterator接口的声明对象接受。
for(Itrator<String> it2 = coll.itrator();it.hasNext();){
Ststem.out.println(it2.next());
}
}
}
2.3、迭代器实现原理
创建集合对象后,获取迭代器实现类对象并且把指针索引指向集合的-1位置。每次判断之后,如果存在下一个元素,使用next()方法将下一个元素取出,同时将索引加一。
2.4、增强for循环
增强for循环(foreach循环)是在JDK1.5之后出现的一个高级for循环,专门用来遍历数组和集合的。它内部原理是一个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
(1)声明格式
底层实现也是使用迭代器,使用增强for简化了迭代器的书写。
for(元素的数据类型 变量:Collection集合or数组){
...
}
(2)例子
public class Demo{
public void main(String[] args){
//增强for循环遍历数组且新的增强for循环必须有被遍历的目标,目标只能是Collection或者是数组。
int[] i = {1,2,3,4,5};
for(int c:i){
System.out.println(c);
}
//增强for循环遍历集合
Collection<int> coll = new ArrayList<>();
coll.add("1");
coll.add("2");
coll.add("3");
for(String s : coll){
System.out.println(s);
}
}
}
第三章、泛型
泛型(),E的位置使用哪种数据类型,集合就存储该类型对象。
集合在定义时,里面存储的数据类型是未知的,这时就会使用E(element元素)、T(type类型)代替数据类型。
public class ArrayList{
public boolean add(E e){};
public E get (int index){};
}
声明对象时,泛型(<>)内使用想要存储的数据类型,该对象的成员方法就会使用相应的数据类型。
3.1、泛型的优点
优点:
(1)避免数据类型的转换,存储什么类型,取出什么类型。
(2)把运行期异常(代码运行异常会抛出的异常)提升到了编译期(代码写完时,平台会自动编译)。
缺点:
泛型是什么数据类型,集合只能存储什么数据类型。
当集合不使用泛型,默认的类型就是Object,可以存储任意类型的数据。但这样的使用方式,集合会变的不安全,易引发异常。
3.2、泛型的定义与使用
(1)定义含泛型的对象
定义一个含有泛型的类,模拟ArrayList集合
泛型是一个未知的数据类型,当不确定什么数据类型时可以使用泛型创建可以接受任意数据类型的类。
public class Demo1<E>{
private E name;
public E getName(){
return name;
}
public E setName(name){
this.name=name;
}
}
(2)定义含泛型的方法
使用:在调用方法的时候确定泛型的数据类型(向方法参数列表中传递什么数据类型的数据,泛型就是什么数据类型)
public class Demo{
//定义含泛型方法
public <M> void methos1(M m){
System.out.println(m);
}
//定义含泛型的静态方法
public static <N> void method2(N n){
System.out.println(n);
}
};
(3)定义含泛型的接口
public interface Demo<I>{
public abstract void method(I i);
}
- 第一种使用方式
- 第二种使用方式
3.3、泛型通配符(?)
通配符(?):代表任意数据类型,不能创建对象使用,只能作为方法的参数。
3.3.1、通配符的基本使用
public class Demo(){
public void main(String[] args){
ArrayList<String> list01 = new ArrayList<>();
list01.add("a");
list01.add("b");
ArrayList<Integer> list02 = new ArrayList<>();
list02.add(1);
list02.add(2);
printArray(list01);
printArray(list02);
//定义一个遍历集合的方法,但是方法参数的泛型不能确定。如果使用String数据类型,调用方法打印list02时会报错;如果使用Integer,调用方法遍历打印list01时会报错;如果使用Object,调用方法打印list01与list02时都会报错。
//泛型不涉及继承这一概念。
public void printArray(ArrayList(?) list){
Iterator<?> it = list.Iterator();
while(it.hasNext()){
Object o =it.next();
System.out.printl(o);
}
}
//泛型只能作为方法参数使用,不能作为集合的泛型内数据类型使用。
}
}
3.3.2、通配符的高级使用
第四章、与集合有关的数据结构
数据在底层存储时的结构及不同数据结构的特性特点。
4.1、栈
栈: stack,简称栈,它是一种运算受限的线性表。
特点:先入后出
入栈(压栈):数据向栈内存储时的操作。
出栈(弹栈):从栈内取出数据时的操作。
4.2、队列
队列:queue,简称队列,也是一种运算受限的线性表。
特点:先进先出
4.3、数组
数组:Array是一个有序的元素列表,数组是在内存中开辟一段连续的空间,并在此空间存放元素。
特点:查询快,增删慢。因为数组地址是连续的,通过索引可以快速查询数据;数组长度是不变的,增/删数组的元素后,必须重新创建一个新数组。
4.4、链表
链表:linked list由一系列节点node(每一个元素就是一个节点)组成,节点可以在运行时动态生成。每个节点包括两部分:一个是存储的数据元素域,另一个是存储下一个节点地址的指针域(本地地址与下一节点地址)。
链表分为两种:单向链表与双向链表。
特点:查询慢,增删快。
单线链表在创建后不增删的情况下顺序不变,但是在增删后顺序会发生改变,因为对链表增删的位置是随机设定。
4.5、红黑树
树:每个节点的分支数不定
二叉树:binary tree,是每个节点不超过2的有序树。
第五章、Map集合
5.1、概述
Java.util.Map<k,v>
Map集合是双列集合,一个元素包含两个值(key,value)。
Map集合中的元素key和value的数据类型可以相同,也可以不同。
Map集合中的元素key是不允许重复的,value是可以重复的。
Map集合中的元素,key和value是一一对应的。
5.2、Map常用子类
public class HashMap implement Map;
(1)HashMap集合底层是哈希表,查询速度特别快。
JDK1.8之前:数组+单向链表。
JDK1.8之后:数组+单向链表/红黑树(链表长度超过8,为了提高查询速度)。
(2)HashMap无序,不保证元素取出顺序与存储顺序相同。
public class LinkedHashMap extends HashMap
(1)LinkedHashMap底层是哈希表+链表。
(2)LinkedHashMap是有序集合 ,保证存储和取出顺序。
5.3、Map集合常用方法
public V put(K key,V value);把指定键值对添加到Map集合中。
public V remove(Object key);把指定键所对应值在Map集合中删除。
public V get(Object key);把指定键所对应的值返回。
public boolean containsKey(Object key);判断集合是否包含指定的键。
(1)put方法
存储键值对时,key不重复,返回值V为null。
存储键值对时,key重复,新存入的值会覆盖原本的值。
(2)remove方法
删除键值对时,key不存在,返回值V为null。
删除键值对时,key存在,返回删除的值。
NullPointException:虽然在下图中删除已经执行,但是使用int类型接收返回参数null会造成异常。
(3)get方法
取值时,key不存在,返回值V为null。
取值时,key存在,返回要取的值。
(4)containsKey方法
key不存在,返回值boolean为false。
key不存在,返回值boolean为true。
5.4、遍历Map集合键找值
public Set<K> KeySet();获取Map集合中多有的键,存储到Set集合中。
public Set<Map,Entry<K,V>> entrySet();获取到Map集合中所有的键值对兑现的集合(Set集合)。