Java集合框架详解
day08所看的视频来源
【千锋】最新版 Java集合框架详解
集合的概念
- 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能
- 和数组的区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
- 位置:java.util.*;
Collection接口
Collection体系集合
Collection父接口
- 特点:代表一组任意类型的对象,无需、无下标、不能重复
- 方法
- boolean add(Object obj) //添加一个对象
- boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中
- void clear() //清空此集合中的所有对象
- boolean contains(object o) //检查此集合中是否包含o对象
- boolean equals(Object o) //比较此集合是否与指定对象相等
- boolean isEmpty() //判断此集合是否为空
- boolean remove(Object o) //在此集合中移除o对象
- int size() //返回此集合中的元素个数
- Object[] toArray() //将此集合抓换成数组
package com.jihe.demo01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Collection接口的使用
* 1.添加元素
* 2.删除元素
* 3.遍历元素
* 4.判断
* @author wgy
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
Collection collection = new ArrayList();
// * 1.添加元素
collection.add("苹果");
collection.add("西瓜");
collection.add("榴莲");
System.out.println("元素个数:"+collection.size());
System.out.println(collection);
// // * 2.删除元素
// collection.remove("榴莲");
// collection.clear();
// System.out.println("删除之后:"+collection.size());
// * 3.遍历元素(重点)
//3.1使用增强for(因为不使用下标)
System.out.println("------------------------");
for(Object object : collection){
System.out.println(object);
}
System.out.println("------------------------");
//3.2迭代器(迭代器专门用来迭代集合的一种方式)
//hasNext();有没有下一个元素
//next();获取下一个元素
//remove();删除当前元素
Iterator it = collection.iterator();
while(it.hasNext()){
String s = (String)it.next();
System.out.println(s);
// it.remove();//删除元素,不能使用collection.remove(s);
}
// System.out.println("元素个数:"+collection.size());//若删除后元素个数:0
// * 4.判断
System.out.println(collection.contains("西瓜"));//true
System.out.println(collection.isEmpty());//false
}
}
List接口与实现类
List子接口
- 特点:有序、有下表、元素可以重复
- 方法:
- void add(int index, Objext o) //在index位置插入对象o
- boolean addAll(int index, Collection c) //将一个集合中的元素添加到此集合中的index位置
- Objext get(int index) //返回集合中指定位置的元素
- List subList(int fromIndex, int toIndex) //返回fromIndex和toIndex之间的集合元素
package com.jihe.demo01;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* List子接口的使用
* 特点:1.有序有下标 2.可以重复i
*/
public class Demo03 {
public static void main(String[] args) {
//先创建集合对象
List list = new ArrayList<>();
//1.添加元素
list.add("苹果");
list.add("小米");
list.add(0,"华为");
System.out.println("元素个数:"+list.size());//元素个数:3
System.out.println(list.toString());//[华为, 苹果, 小米]
// //2.删除元素
// list.remove(0);
// System.out.println("删除之后:"+list.size());//删除之后:2
// System.out.println(list.toString());//[苹果, 小米]
//3.遍历
//3.1使用for遍历
System.out.println("---------使用for---------");
for(int i=0; i
package com.jihe.demo01;
import java.util.ArrayList;
import java.util.List;
/**
* list的使用
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
List list = new ArrayList();
//1.添加数字数据(自动装箱)
list.add(20);//已经变成包装类
list.add(30);
list.add(40);
list.add(50);
list.add(60);
System.out.println("元素个数"+list.size());//元组个数5
System.out.println(list.toString());//[20, 30, 40, 50, 60]
//2.删除操作
list.remove(new Integer(20));//如果想要删除值为20的就要先new Interger把基本类型转成引用类型
System.out.println("删除元素:"+list.size());//删除元素:4
System.out.println(list.toString());//[30, 40, 50, 60]
//3.补充方法subList,返回自己和
List sublist = list.subList(1,3);//包含1不包含3
System.out.println(sublist.toString());//[40, 50]
}
}
List实现类
- ArrayList[重点]:
- 数组结构实现,查询快、增删慢
- JDK1.2版本加入的,运行效率快、线程不安全
- Vector:
- 数组结构实现,查询快、增删慢
- JDK1.0版本的,运行效率慢、线程安全
- LinkedList:
- 链表结构实现,增删快,查询慢
ArrayList使用
- 特点:有序、有下表、元素可以重复
- 使用remove()方法的时候,想要做到用相同数值来删除对象,就需要重写方法equals()比较两者数值return true,否则比较的是地址无法用相同数值为条件remove()对象
ArrayList源码分析
- 源码分析:
- DEFAULT_CAPACITY = 10; 默认容量
- 注意:如果没有向集合中添加任何元素时,容量为0,添加一个元素之后,容量为10,扩容原来的1.5倍
- elementData 存放元素的数组
- size 实际的元素个数
- add()添加元素
- DEFAULT_CAPACITY = 10; 默认容量
Vector使用(使用频率不高)
//枚举器遍历
Enumeration en = vector.elements();
while(en.hasMoreElements()){
String o = (String)en.nextElement();
sout(o);
}
LinkedList使用
- 链表结构实现,增删快,查询慢(双向链表)
package com.jihe.demo01;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* LinkedList的使用
* 存储结构:双向链表
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
LinkedList linkedList = new LinkedList<>();
//1.添加元素
Student s1 = new Student("刘德华",20);
Student s2 = new Student("郭富城",22);
Student s3 = new Student("梁朝伟",18);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s3);
System.out.println("元素个数:"+linkedList.size());
System.out.println(linkedList.toString());
// //2.删除
// linkedList.remove(new Student("刘德华",20));
// System.out.println("删除之后:"+linkedList.size());
// linkedList.clear();
//3.遍历
//3.1for遍历
System.out.println("----------------for--------------");
for(int i=0; i
泛型和工具类
泛型概念
- Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递
- 常见类型有泛型类、泛型接口、泛型方法
- 语法:
T成为类型占位符,表示一种引用类型
- 好处:
- 提高代码的重用性
- 防止类型转换异常,提高代码的安全性
//MyGeneric.java
package com.jihe.demo03;
/**
* 泛型类
* 语法:类名
* T是类型占位符,表示一种引用类型,如果编写多个使用都好隔开
*/
public class MyGeneric {
//使用泛型T
//1.创建变量
T t;
//2.作为方法的参数,不能T t1 = new T();,因为不知道他是不是私有的
public void show(T t){
System.out.println(t);
}
//3.泛型作为方法的返回值
public T getT(){
return t;
}
}
//TestGeneric
package com.jihe.demo03;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//注意:1.泛型只能使用引用类型 2.不同泛型对象之间不能相互赋值
MyGeneric myGeneric = new MyGeneric();
myGeneric.t="hello";
myGeneric.show("大家好,加油");//大家好,加油
String string = myGeneric.getT();
MyGeneric myGeneric2 = new MyGeneric();
myGeneric2.t = 100;
myGeneric2.show(200);//200
Integer integer = myGeneric2.getT();
}
}
泛型接口
//MyInterface.java
package com.jihe.demo03;
/**
* 泛型接口
* 语法:接口名
* 注意:不能泛型静态常量
*/
public interface MyInterface {
String name = "张三";
T server(T t);
}
两种泛型接口实现
//MyInterfaceImpl.java
//先定义泛型类型,如下定义为String型
package com.jihe.demo03;
public class MyInterfaceImpl implements MyInterface {
@Override
public String server(String s) {
System.out.println(s);
return null;
}
}
//MyInterfaceImpl2.java
//使用对象定义泛型类型,也就是实例化的时候,泛型类型和对象类型一直,TestGeneric里可以看出
package com.jihe.demo03;
public class MyInterfaceImpl2 implements MyInterface{
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
//TestGeneric.java
package com.jihe.demo03;
public class TestGeneric {
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.server("xxxxxx");//因为是String定义,所以只能传入String
MyInterfaceImpl2 impl2 = new MyInterfaceImpl2<>();////泛型T传入Interger类型
impl2.server(1000);
}
}
泛型集合
- 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
- 特点:编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱)
- 不同泛型之间引用不能相互赋值,泛型不存在多态
package com.jihe.demo03;
import java.util.ArrayList;
public class TestGeneric {
public static void main(String[] args) {
//泛型集合
ArrayList arrayList = new ArrayList();//泛型限定了必须是String才能add
arrayList.add("xxx");
arrayList.add("yyy");
for (String string : arrayList){//因此这里只能是String,而不会出现强制类型转换的问题
System.out.println(string);
}
}
}
Set接口与实现类
Set集合概述
- 特点:无序、无下标、元素不可重复
- 方法:全部继承自Collection中的方法
Set接口的使用
一般都用HashSet
package com.jihe.demo04;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* 测试Set接口的使用
* 特点:1.无序、没有下表 2.不能重复
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
Set set = new HashSet<>();
//1.添加数据
set.add("苹果");//add不能加两个一样的,也就是不能重复
set.add("小米");
set.add("华为");
//2.删除
set.remove("小米");
//3.遍历【充电】
//3.1增强for
System.out.println("-----------增强for---------");
for(String string : set){
System.out.println(string);
}
System.out.println("-----------使用迭代器---------");
//3.2使用迭代器
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//4.判断
System.out.println(set.contains("华为"));
System.out.println(set.isEmpty());
}
}
Set实现类
- HashSet【重点】:
- 基于HashCode实现元素不重复
- 当存入元素的哈希码(HashCode)相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
- TreeSet:
- 基于排序顺序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实习Comparable接口,指定排序规则
- 通过CompareTo(重写后可以比较对象)方法确定是否为重复元素
- 可以通过两种重写方法如下
//Person.java
package com.jihe.demo04;
import java.util.Objects;
public class Person implements Comparable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
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);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
//先按姓名比,然后按年龄比
public int compareTo(Person o) {
int n1=this.getName().compareTo(o.getName());
int n2=this.age-o.getAge();
return n1==0?n2:n1;//如果n1不为0则是n1,如果为0就是n2
}
}
package com.jihe.demo04;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 使用TreeSet保存数据
* 存储结构:红黑树
* 要求:要素必须要实现Comparable接口
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
TreeSet persons = new TreeSet<>();
//1.添加元素
Person p1=new Person("刘德华",20);
Person p2=new Person("林志玲",22);
Person p3=new Person("梁朝伟",25);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
//直接重写也可以,这样子类里就不用implements Comparable
TreeSet persons2 = new TreeSet<>(new Comparator() {
@Override
public int compare(Person o1, Person o2) {
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Person p4=new Person("刘德华",20);
Person p5=new Person("林志玲",22);
Person p6=new Person("梁朝伟",25);
persons2.add(p1);
persons2.add(p2);
persons2.add(p3);
System.out.println(persons.toString());
}
}
Map接口与实现类
- 特点:
- 存储键值对
- 键不能重复,值可以重复
- 无序
//Map方法
package com.jihe.demo05;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Map接口的使用
* - 特点:
* - 存储键值对
* - 键不能重复,值可以重复
* - 无序
* -
*/
public class Demo01 {
public static void main(String[] args) {
//创建Map集合
Map map = new HashMap<>();
//1.添加元素,注意如果key一样,value不一样,会吧value替换掉,也就是覆盖
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
// map.put("cn","zhongguo");
System.out.println("元素个数:"+map.size());
System.out.println(map.toString());
//3.遍历
//3.1使用keySet();
System.out.println("-----------使用keySet(),增强for--------");
// Set keyset = map.keySet();
for (String key : map.keySet()) {//map.keySet()获得的是key集合
System.out.println(key+"----"+map.get(key));//用map.get(key)获得value
}
//3.2使用entrySet();
System.out.println("-----------使用entrySet(),增强for--------");
// Set> entries = map.entrySet();
for(Map.Entry entry : map.entrySet()){//map.entrySet()把key和value一起封装成一个Entry获得
System.out.println(entry.getKey()+"------------"+entry.getValue());//调用getKey()和getValut()获得
}
//4.判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("泰国"));
}
}
Map集合的实现类
- HashMap【重点】
- JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value
- 刚创建HashMap之后没有添加元素table=null,size=0,目的是节省空间
- HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时候,table容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后为原来的2倍,目的是减少调整元素的个数
- jdk1.8当每个链表长度大于8,并且元素个数大于64时,会调整为红黑树,目的是提高执行效率
- jdk1.8当链表长度小于6时,调整成链表
- jdk1.8以前,链表是头插入,jdk1.8以后是尾插入
- Hashtable(基本不用了):
- JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value
- Properties:
- Hashtable的子类,要求key和value都是String。通常用于配置文件的读取‘
- TreeMap:
- 实现了SortedMap接口(是Map的子接口),可以对key自动排序
Collections工具类
package com.jihe.demo05;
import java.util.*;
public class Demo02 {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(20);
list.add(5);
list.add(12);
list.add(30);
list.add(6);
//sort 排序
System.out.println("排序之前"+list.toString());
Collections.sort(list);
System.out.println("排序之后"+list.toString());
//binarySearch 二分查找
int i = Collections.binarySearch(list,6);
System.out.println(i);
//copy 赋值
List dest = new ArrayList<>();
for (int k = 0; k < list.size(); k++) {
dest.add(0);
}
Collections.copy(dest,list);//两个数组大小要一样才能copy,所以先for添加0
System.out.println(dest.toString());
//reverse 反转
Collections.reverse(list);
System.out.println("反转之后"+list);
//shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后"+list);
//补充,list转成数组
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);//是大的那个的长度,所以0就默认变成list的长度
System.out.println(Arrays.toString(arr));
//数组转成集合
String[] names = {"张三","李四","王五"};
//转换后的集合是一个受限集合,不能添加和删除,也就是不能add和remove
List list2 = Arrays.asList(names);
System.out.println(list2);
//把基本类型数组转换成集合时,需要修改为包装类
Integer[] nums = {100,200,300,400,500};
List list3 = Arrays.asList(nums);
System.out.println(list3);
}
}