集合框架的总结和复习
1.数组存储数据方面的特点和弊端
数组存储多个数据方面的特点
:
>数组一旦初始化,其长度就是确定的
>数组中的多个元素是依次紧密排列的、有序的、可重复的
>(优点)数组一旦初始化完成,其元素的类型就是确定的,不是此类型的元素,就不能添加到此数组中
int[] arr = new int[10];
arr[0]=1;
arr[1]="aaa";//编译报错
Object[] arr1 = new Object[10];
arr1[0] = new String();
arr1[1] = new Date();
>(优点)元素的类型既可以是基本数据类型,也可以是引用数据类型
数组存储多个数据方面的弊端
:
> >数组一旦初始化,其长度就不可变了
> >数组中存储数据特点的单一性、对于无序的、不可重复的场景的多个数据就无能为力了
> >数组中可用的方法、属性都极少。具体的需求,都需要自己来组织相关的代码逻辑
> >针对于数组中元素的删除、插入操作、性能比较差
2.集合框架的概述
java.util.Collection:存储一个一个的数据
|----子接口:List:有序的可以重复的数据("动态"数组) |---- ArraysList(主要的实现类)、LinkedList、Vector |----子接口:Set:存储无序的不可重复的数据(高中学习的集合) |---- HashSet(主要的实现类)、LinkHashSet、TreeSet
java.util.Map:存储一对一对的数据(key-value键值对,(x1,y1)
(x2,y2)—>y=f(x),类似于高中的函数)|---- HashMap(主要的实现类)、LinkedHashMap、TreeMap
学习的程度把握:
层次1:针对于具体特点的多个数据,知道选择相应的适合的接口的主要实现类,会实例化,会调用常用的方法
层次2:区分接口中不同实现类的区别
层次3:①针对于常用的实现类,需要熟悉底层的源码 ②熟悉常见的数据结构
3.Collection的常用方法
3.1常用方法
自己定义的类
package com.huige01.collection集合框架;
import java.util.Objects;
public class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
System.out.println("Person equals()...");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
}
add(Object obj)
addAll(Collection coll)
测试代码:
/**
* (1)add(E obj):添加元素对象到当前集合中
* (2)addAll(Collection other):添加other集合中的所有元素对象到当前集合中,即this = this ∪ other
*/
@Test
public void test1() {
Collection coll = new ArrayList();
//add()
coll.add("AA");
coll.add(123);//自动装箱
coll.add("你好");
coll.add(new Object());
coll.add(new Person("Tom", 12));
System.out.println(coll.size());//5
System.out.println(coll);
//addAll(Collection other):添加other集合中的所有元素对象到当前集合中,即this = this ∪ other
Collection coll1 = new ArrayList();
coll1.add("BB");
coll1.add(456);
coll.addAll(coll1);
System.out.println(coll);
//size():获取当前集合中元素的个数
System.out.println(coll.size());//7
}
clear()
isEmpty()
size()
contains(Object obj)
containsAll(Collection coll)
retainAll(Collectioncoll)
remove(Object obj)
removeAll(Collection coll)
hashCode()
equals()
toArray()
测试代码:
/*
* (3)int size():获取当前集合中实际存储的元素个数
(4)boolean isEmpty():判断当前集合是否为空集合
(5)boolean contains(Object obj):判断当前集合中是否存在一个与obj对象equals返回true的元素
(6)boolean containsAll(Collection coll):判断coll集合中的元素是否在当前集合中都存在。即coll集合是否是当前集合的“子集”
(7)boolean equals(Object obj):判断当前集合与obj是否相等
* */
@Test
public void test2() {
Collection coll = new ArrayList();
//add()
coll.add("AA");
coll.add(123);//自动装箱
coll.add("你好");
coll.add(new Object());
coll.add(new Person("Tom", 12));
//boolean isEmpty():判断当前集合是否为空集合
System.out.println(coll.isEmpty());
//boolean contains(Object obj):判断当前集合中是否存在一个与obj对象equals返回true的元素
System.out.println(coll.contains("AA"));//true
System.out.println(coll.contains(128));//true
System.out.println(coll.contains(new Person("Tom", 12)));//false--->true
//boolean containsAll(Collection coll):判断coll集合中的元素是否在当前集合中都存在。即coll集合是否是当前集合的“子集”
Collection coll1 = new ArrayList();
//add()
coll1.add("AA");
coll1.add(123);
// coll1.add("BB");
System.out.println(coll.containsAll(coll1));
}
/*
* (8)void clear():清空集合元素
(9) boolean remove(Object obj) :从当前集合中删除第一个找到的与obj对象equals返回true的元素。
(10)boolean removeAll(Collection coll):从当前集合中删除所有与coll集合中相同的元素。即this = this - this ∩ coll
(11)boolean retainAll(Collection coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与coll集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即this = this ∩ coll;
* */
@Test
public void test3() {
Collection coll = new ArrayList();
//add()
coll.add("AA");
coll.add("AA");
coll.add(123);//自动装箱
coll.add("你好");
coll.add(new Object());
coll.add(new Person("Tom", 12));
// coll.clear();
// System.out.println(coll);
// System.out.println(coll.size());//0
//boolean remove(Object obj) :从当前集合中删除第一个找到的与obj对象equals返回true的元素。
coll.remove(new Person("Tom", 12));
coll.remove("AA");
System.out.println(coll);
}
/*
* (12)Object[] toArray():返回包含当前集合中所有元素的数组
(13)hashCode():获取集合对象的哈希值
(14)iterator():返回迭代器对象,用于集合遍历
* */
@Test
public void test4() {
Collection coll = new ArrayList();
coll.add("AA");
coll.add("AA");
coll.add(123);//自动装箱
coll.add("你好");
coll.add(new Person("Tom", 12));
//集合-->数组
Object[] array = coll.toArray();
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
//hashCode()
System.out.println(coll.hashCode());
}
/*
* 数组转换为集合的方式
* */
@Test
public void test5(){
String[] arr = new String[]{"AA", "BB", "CC"};
List list = Arrays.asList(arr);
System.out.println(list);
}
@Test
public void test6() {
Integer[] arr = new Integer[]{1, 2, 3};
List<Integer> list = Arrays.asList(arr);
System.out.println(list.size());//3
System.out.println(list);
int[] arr1 = new int[]{1, 2, 3};
List list1 = Arrays.asList(arr1);
System.out.println(list1.size());//1
System.out.println(list1);
}
iterator()---->引出迭代器接口
向Collection中添加元素的要求:
> 要求元素所属的类一定要重写equals()!
集合与数组的相互转换:
> 集合 -->数组:toArray()
> 数组 -->集合:调用Arrays的静态方法asList(Object ....objs);返回的是一个List
3.2迭代器接口
- 设计模式的一种
- 迭代器不负责数据的存储;负责对结合类的遍历
具体代码的实现:
1. 如何获取迭代器(Iterator)对象?
Iterator iterator = coll.iterator();
2. 如何实现遍历(代码实现)
while (iterator.hasNext()) {
System.out.println(iterator.next());//next() :①指针下移 ②将下移以后集合位置上的元素返回
}
4.Collection接口
4.1 List子接口
- 常用方法
> 小结:
> 增
> add(Object obj)
> addAll(Collection coll)
> 删
> remove(Object obj)
> remove(int index)
> 改
> set(int index,Object obj)
> 查
> get(int index)
> 插
> add(int index, Object ele)
> addAll(int index, Collection eles)
> 长度
> size()
> 遍历
> iterator():使用迭代器进行遍历
> 增强for循环
> 一般的for循环
- List及其实现类特点
java.util.Collection:存储一个一个的数据
|----子接口:List:有序的可以重复的数据("动态"数组)
|---- ArraysList:List主要的实现类;线程不安全,效率高;底层使用Object[]数组存储
在添加数据,查找数据时,效率较高;在插入,删除数据时,效率较低
|----- LinkedLis:底层使用双向链表的方式进行存储;在对集合中的数据进行频繁删除和插入操作时建议使用此类
在添加数据,查找数据时,效率较低;在插入,删除数据时,效率较高
|----Vector:List的古老的实现类;线程安全的,效率低;底层使用Object[]数组存储
[面试题]:ArrayList,Vector的区别? ArrayList,LinkedList的区别?
4.2 Set子接口
- Set中的常用方法都是Collection中声明的方法,没有新增的方法
- 常见的实现类的对比
Set及其实现类特点
java.util.Collection:存储一个一个的数据
|----子接口:Set:存储无序的不可重复的数据(高中学习的集合)
|---- HashSet:主要的实现类;底层使用的是HashMap,即使用数组+单向链表+红黑树结构进行存储(jdk8中)
|---- LinkHashSet:是HashSet的子类;在现有的数组+单向链表+红黑树结构的基础上,又添加了
一组双向链表,用于记录添加元素的先后循序,即我们可以按照添加元素的循序
实现遍历,便于频繁的查询操作
|---- TreeSet:底层使用红黑树存储,可以按照添加的元素的指定的属性的大小顺序进行遍历
- 难点Set中无序性、不可重复性的理解(以HashSet及其子类为例说明)
>无序性: != 随机性
添加元素的顺序和遍历元素的顺序不一致,是不是就是无序性呢? No!
到底什么是无序性?与添加元素的位置有关,不像ArrayList一样依次紧密排列的
这里是根据添加的元素的哈希值,计算的其在数组中的储存位置,此位置不是依次排列的,表现为无序性
>不可重复性:添加到Set中的元素是不能相同的
比较的标准,需要判断HashCode()得到的哈希值与equals()方法得到boolean型的结果
哈希值相同且equals()返回true,则认为元素是相同的
- 添加到HashSet/LinkedHashSet中元素的要求:
要求元素所在的类要重写两个方法:equals() 和 hashCode()同时,
要求equals() 和 hashCode()要保持一致性!我们只需要在idea中自动生成两个方法的重写即可,即能保证两个方法的一致性
- TreeSet的使用:
了解即可
1 底层的数据结构:红黑树
2 添加数据后的特点:可以按照\添加元素的指定的属性大小顺序进行遍历
3 向TreeSet中添加的元素的要求:
>要求添加到TreeSet中的元素必须是同一个类型的对象,否则会报ClassCastException异常
4 判断数据是否相同的标准
>不再是考虑hashCode()和equals()方法了,也就意味着添加到TreeSet中的元素所在的类不需要重写hashCode()和equals()方法了
>比较元素大小的或比较元素是否相等的标准就是考虑自然排序或定制排序中,compareTo()或compare()的返回值
如果compareTo或compare()的返回值为0,则认为两个对象是相等的,由于TreeSet中不能存放相同的元素,则
后一个相等的元素就不能添加到TreeSet中
5.Map接口
- 常用的方法
小结:
增:
put(Object key,Object value)
putAll(Map m)
删:
remove(Object key)
改:
put(Object key,Object value)
putAll(Map m)
查:
get(Object key)
长度:
size()
遍历:
遍历key集:Set keySet()
遍历value集:Collection values()
遍历entry集:Set entrySet()
- 常用的实现类
Map及其实现类对比
java.util.Map:存储一对一对的数据(key-value键值对,(x1,y1) (x2,y2)--->y=f(x),类似于高中的函数)
|---- HashMap:主要的实现类;线程不安全的,效率高;可以添加null的key和value值;底层使用数组+单向链表+红黑树结构存储(jdk8)
|---- LinkedHashMap:是HashMap的子类;在HashMap使用的数据结构的基础上,增加了一对双向列链表,用于记录添加的元素的先后顺序
进而我们在遍历元素时,就可以按照添加的顺序显示
开发中,对于频繁的遍历操作,建议使用此类
|---- TreeMap:底层使用的红黑树存储;可以按照添加的key-value中的key元素的指定属性的大小顺序进行遍历,需要考虑使用①自然排序②定制排序
|---- Hashtable:古老实现类;线程安全的,效率低;不可以添加null的key或value值;底层使用数组+单向链表结构存储的(jdk8)
|---- Properties:其key和value都是String类型,常用来处理属性文件
[面试题]
区别HashMap和Hashtable; 区别HashMap和LinkedHashMap;HashMap的底层实现(①new HashMap() ②put(key,value))
- HashMap元素的特点
>HashMap中的所有的key彼此之间是不可重复的,是无序的,所有的key就构成了一个Set集合,--->key所在的类要重写hashCode()和equals()
>HashMap所有的value彼此之间是可重复的,是无序的,所有的value一个Collection集合--->value所在的类要重写equals()
>HashMap中的一个key-value,就构成了一个Entry
>HashMap中所有的Entry彼此之间是不可重复的,是无序的,所有的Entry就构成了一个Set集合
- (了解)TreeMap的使用
>底层使用的红黑树存储;可以按照添加的key-value中的key元素的指定属性的大小顺序进行遍历,需要考虑使用①自然排序②定制排序
>需要考虑使用①自然排序②定制排序
>要求:向TreeMap中添加的key必须是同一个类型的对象
- (重要) Properties的使用
public class PropertiesTest {
@Test
public void test1() throws IOException {//注意:因为设计到流的操作,为了确保流能关闭,建议使用try-catch-finally
//方式1:数据和代码耦合度高;如果修改的话,需要重新的去编译代码,打包发布,繁琐
//数据
// String name = "Tom";
// String password = "abc123";
//代码:用于操作name,password
//....
//方式2:将数据封装到具体的配置文件中,在程序中读取配置文件中的信息,实现了
//数据和代码的解耦;由于我们没有修改代码,就省去了重新编译和打包的事情
File file = new File("info.properties");//注意:要提前=创建好
// System.out.println(file.getAbsolutePath());
FileInputStream fis = new FileInputStream(file);
Properties pros = new Properties();
pros.load(fis);//加载流中的文件中的数据
//读取文件中的数据
String name = pros.getProperty("name");
String password = pros.getProperty("password");
System.out.println(name+":"+password);
fis.close();
}
// public static void main(String[] args) {
// File file = new File("info.properties");
// System.out.println(file.getAbsolutePath());
// }
}
6.Collections工具类的使用
区分Collection 和 Collections
Collection:集合框架中的用于存储一个一个元素的接口,又分为List和Set等子接口
Collections:用于操作集合框架的一个工具类,此时的集合框架包括:Set,List,Map
- 熟悉掌握Collections的方法
排序操作:
- reverse(List):反转 List 中元素的顺序
- shuffle(List):对 List 集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
- sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
- swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
- Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素
- Object min(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最小元素
- int binarySearch(List list,T key)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且必须是可比较大小的,即支持自然排序的。而且集合也事先必须是有序的,否则结果不确定。
- int binarySearch(List list,T key,Comparator c)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且集合也事先必须是按照c比较器规则进行排序过的,否则结果不确定。
- int frequency(Collection c,Object o):返回指定集合中指定元素的出现次数
复制、替换
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
- 提供了多个unmodifiableXxx()方法,该方法返回指定 Xxx的不可修改的视图。
添加
- boolean addAll(Collection c,T... elements)将所有指定元素添加到指定 collection 中。
同步
- Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题: