一、集合概念
- 对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
- 位置:java.util.*;
集合和数组区别:
- 数组长度固定,集合长度不固定。
- 数组可以存储基本类型和引用类型,集合只能存储引用类型。
- int[] a Student[]
二、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() | 将此集合转换成数组 |
注:遍历同时不能使用集合删除方法,否则出现并发修改异常,可使用迭代器的删除方法。
三、List接口与实现类【重点】
3.1 List接口
特点:有序、有下标、元素可以重复。
继承Collection接口。
常用方法:
方法 | 描述 |
---|---|
void add(int index, Object o) | 在index位置插入对象o。 |
boolean addAll(int index, Collection c) | 将一个集合中的元素添加到此集合中的index位置。 |
Object get(int index) | 返回集合中指定位置的元素。 |
List subList(int fromIndex, int toIndex) | 返回fromIndex和toIndex之间的集合元素。 |
3.2 List实现类
3.2.1 ArrayList
- 数组结构实现,查询快、增删慢。
- JDK1.2版本、线程不安全。
案例演示:ArrayList保存对象
package com.qfedu.test03;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
//1.List 的包注意一下
//1.1
public class Test01 {
public static void main(String[] args) {
//1. 用多态方式创建一个list
List list = new ArrayList();
//3.1 获取长度
int size = list.size();
System.out.println(size);
//2. add 添加数据
list.add("小乔");
list.add("大乔");
list.add("老乔");
list.add("乔太太");
//3.浏览元素
size = list.size();
System.out.println(size);
/*List list1 = null;
int size1 = list1.size();
System.out.println(size1);*/
System.out.println("============第一种方式");
//3.1循环输出
for(int i=0; i<=list.size()-1; i++) {
String o = (String)list.get(i);
System.out.println(o);
}
System.out.println("===========第二种方式输出===============");
for (Object o : list) {
System.out.println(o);
}
System.out.println("=========第三种方式============");
//1.获取迭代器
Iterator iterator = list.iterator(); //hasNext() 有下一个元素吗
while (iterator.hasNext()) {
System.out.println(iterator.next()); // next() 取元素
}
//4. 清空方法
System.out.println("=====清空方法 clear======");
System.out.println(list);
//list.clear();
System.out.println(list);
//5.包含 contains
System.out.println("======contains包含");
boolean b = list.contains("小乔3");
System.out.println(b);
//6.equals
System.out.println("======equals=====");
List list2 = list;
boolean equals = list.equals(list2);
System.out.println(equals);
System.out.println("====内存地址 不同,但内容相同");
List list3 = new ArrayList();
list3.add("小乔");
list3.add("大乔");
list3.add("老乔");
list3.add("乔太太");
boolean equals1 = list.equals(list3);
System.out.println(equals1);
System.out.println("=======判断是否是空的====");
//7判断是否是空的 对象不能为空 null, 其实就是长度 size() =0;
List list4 = new ArrayList();
boolean empty = list4.isEmpty();
System.out.println(empty);
//list 和 数组 之间可以互相 转换
System.out.println("======list==> array");
Object[] objects = list.toArray();
System.out.println(Arrays.toString(objects));
System.out.println("=======array==> list");
List<Object> list1 = Arrays.asList(objects);
System.out.println(list1);
System.out.println("=========== addAll 把一个list 整体添加过去");
//8 addAll 把一个list 整体添加过去
boolean b1 = list.addAll(list1);
System.out.println(list);
System.out.println(list1);
//9.移除
System.out.println("======移除元素");
boolean bb1 = list.remove("小乔");
System.out.println(bb1);
boolean bb2 = list.remove("小乔");
System.out.println(list);
System.out.println("====移除并返回移除的元素");
Object remove = list.remove(5);
System.out.println(remove);
System.out.println(list);
System.out.println("======截取==========");
//10截取 方法 后边的下标不包含
List list5 = list.subList(2, 4);
System.out.println(list5);
System.out.println("============指定位置 添加");
list.add(1,"乔奶奶");
System.out.println(list);
}
}
equalsp实现源码
ArrayList的动态扩容机制:
elemntData.length : 长度
超过长度:
3.2.2 LinkedList
- 链表结构实现,增删快,查询慢。
- JDK1.2版本、线程不安全。
案例演示:LinkedList保存对象数据。
package com.qfedu.test03;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Test03 {
public static void main(String[] args) {
//1. 创建对象
List list = new LinkedList();
//2.添加元素
list.add("曹操");
list.add("曹丕");
list.add("曹植");
list.add("曹冲");
//3.
System.out.println("====展示");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("======for增强");
for (Object o : list) {
System.out.println(o);
}
System.out.println("======迭代一下");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("===清除");
//list.clear();
System.out.println(list);
//新增--插入
System.out.println("======新增--插入");
list.add(3,"曹操的儿子");
list.add(3,"曹操的儿子");
System.out.println(list);
//3.修改
System.out.println("======修改 ");
list.set(2,"真");
System.out.println(list);
//4.删除
System.out.println("=====删除");
list.remove("曹操的儿子");
System.out.println(list);
list.remove(3);
System.out.println(list);
//5. 长度
System.out.println("=====长度");
int size = list.size();
System.out.println(size);
//6.空 list 不能是null
System.out.println("===长度是否为0 isEmpty();");
boolean empty = list.isEmpty();
System.out.println(" list <==> array");
Object[] a1 = list.toArray();
System.out.println(Arrays.toString(a1));
List<Object> list1 = Arrays.asList(a1);
System.out.println(list1);
}
}
ArrayList和LinkedList区别:
- ArrayList存储结构是数组,查找、遍历效率高。
- LinkedList存储结构是双向链表,删除、添加效率高。
3.2.3 Vector
数组结构实现,查询快、增删慢。
JDK1.0版本,线程安全、运行效率比ArrayList较慢。
案例演示:使用Vector保存数据。
package com.qfedu.test03;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
public class Test04 {
public static void main(String[] args) {
//1.定义
List list = new Vector();
//2.放值
list.add("张飞");
list.add("关羽");
list.add("刘大耳朵");
System.out.println(list);
for (Object o : list) {
System.out.println(o);
}
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
System.out.println(o);
}
Vector c = (Vector)list;
Enumeration elements = c.elements();
while (elements.hasMoreElements()) {
System.out.println(elements.nextElement());
}
}
}
四、泛型
4.1 泛型概念
概念:
- Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
- 常见形式有泛型类、泛型接口、泛型方法。
语法:
- <T,…> T称为类型占位符,表示一种引用类型。
优点:
- 提高代码的重用性。
- 防止类型转换异常,提高代码的安全性。
案例演示:创建泛型类。
package com.qfedu.test01;
//准备一个Hero类
public class Hero {
//名字
private String name;
//生命值
private int live;
public Hero() {
}
// 构造器赋值 Alt+insert constronter
public Hero(String name, int live) {
this.name = name;
this.live = live;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLive() {
return live;
}
public void setLive(int live) {
this.live = live;
}
@Override
public String toString() {
return "Hero{" +
"name='" + name + '\'' +
", live=" + live +
'}';
}
}
public interface IHeroDao {
//准备接口IHeroDao
//查询英雄的数据,返回查询结果
//参数: 无
//返回值类型: List
public List selectAll();
}
package com.qfedu.test01;
import java.util.ArrayList;
import java.util.List;
//接口实现类HeroDaoImple: 演示三种用法
//1.泛型 :规范数据类型 <T>
//2.第一种是往对象上规定泛型
//3.第二种在类上边写泛型,可以指定三个地方的类型: 属性 , 方法的返回值和方法的参数
//4.第三种用法在类上没有写,直接想在方法上写,: 参数传入的是什么类型,你给我返回什么类型
public class HeroDaoImpl<T> implements IHeroDao{
T a;
public void sout(){
//打印a类型,
Class aClass = a.getClass();
System.out.println(a.getClass().getName());
}
public T aa(T b ) {
return b;
}
// ctrl+i 实现接口:重写方法 ctrl+o 继承:重写方法
@Override
public List selectAll() {
//.1创建list对象
//List list = new ArrayList();
// 规定List中只能装 Hero对象,
// List<T> list = new ArrayList<T>();// 后边的T可以省略
List<Hero> list = new ArrayList<Hero>();
//2.准备三个Hero对象
Hero h1 = new Hero("武大",1200);
Hero h2 = new Hero("武二",10000);
Hero h3 = new Hero("潘经理",100);
Hero h4 = new Hero("西门xxx",100);
//3.添加到list
list.add(h1);
list.add(h2);
list.add(h3);
list.add(h4);
list.add(new Hero("王妈妈",1007));
/*Test01 t = new Test01();
list.add(h4);*/
return list;
}
}
//1.dao层对象
IHeroDao hd = new HeroDaoImpl();
List bb = hd.selectAll();
System.out.println(bb);
HeroDaoImpl<String> hd2 = new HeroDaoImpl();
hd2.a ="1";
hd2.sout();
HeroDaoImpl<String> hd3 = new HeroDaoImpl();
public class Test01 {
//单独演示:泛型方法。
public <T> T aa(T t) {
return t;
}
}
Test01 t = new Test01();
String aa = t.aa("123");
Hero aa1 = t.aa(new Hero());
int[] aa2 = t.aa(new int[1]);
案例演示:泛型接口。
package com.qfedu.test02;
import java.util.List;
public interface IHeroDao<T> {
public List<T> selectAll();
}
package com.qfedu.test02;
import java.util.List;
public class HeroDaoImpl implements IHeroDao {
@Override
public List selectAll() {
return null;
}
}
package com.qfedu.test02;
import com.qfedu.test01.Hero;
import java.util.List;
public class TMain {
public static void main(String[] args) {
IHeroDao<String> hd = new HeroDaoImpl();
List<String> strings = hd.selectAll();
}
}
注:1、泛型只能使用引用类型。 2、不同泛型类型对象之间不能相互赋值。
4.2 泛型集合
参数化类型、类型安全的集合,强制集合元素的类型必须一致。
特点:
- 编译时即可检查,而非运行时抛出异常。
- 访问时,不必类型转换(拆箱)。
- 不同泛型之间引用不能相互赋值,泛型不存在多态。
public class TestArrayList2 {
public static void main(String[] args) {
ArrayList<String> arrayList=new ArrayList<String>();
arrayList.add("xxx");
arrayList.add("yyy");
// arrayList.add(10);
// arrayList.add(20);
for (String string : arrayList) {
System.out.println(string);
}
ArrayList<Student> arrayList2=new ArrayList<Student>();
Student s1=new Student("刘德华", 20);
Student s2=new Student("郭富城", 22);
Student s3=new Student("梁朝伟", 18);
arrayList2.add(s1);
arrayList2.add(s2);
arrayList2.add(s3);
Iterator<Student> it=arrayList2.iterator();
while(it.hasNext()) {
Student s=it.next();
System.out.println(s.toString());
}
}
}
五、Collections工具类
集合工具类,定义了除了存取以外的集合常用方法。
常见方法:
方法 | 描述 |
---|---|
public static void reverse(List<?> list) | 反转集合中元素的顺序 |
public static void shuffle(List<?> list) | 随机重置集合元素的顺序 |
public static void sort(List list) / | 升序排序(元素类型必须实现Comparable接口) |
public static int binarySearch( list, T key) | 二分查找 |
案例演示:
package com.qfedu.test04;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class Test01 {
public static void main(String[] args) {
//1.多态创建对象
List<Integer> list = new ArrayList<Integer>();
list.add(34);
list.add(12);
list.add(56);
list.add(30);
System.out.println(list);
//1第一个方法反转
System.out.println("=====反转=====");
Collections.reverse(list);
System.out.println(list);
//2.
System.out.println("======随机重置 ");
Collections.shuffle(list);
System.out.println(list);
//3.sort
System.out.println("====sort排序");
Collections.sort(list);
System.out.println(list);
Collections.shuffle(list);
//4.
System.out.println("===二分查找");
Collections.sort(list);
int i = Collections.binarySearch(list, new Integer(34));
System.out.println(list);
System.out.println(i);
}
}
六、Set集合
6.1 Set接口
特点:无序、无下标、元素不可重复。
方法:全部继承自Collection中的方法。
使用foreach循环遍历:
for(数据类型 局部变量 : 集合名){
//循环内部的局部变量,代表当次循环从集合中取出的对象
}
6.2 Set实现类
6.2.1 HashSet
- 基于HashCode实现元素不重复。
- 当存入元素的哈希码相同时,会调用==或equals进行确认,结果为true,拒绝后者存入。
- 采用的哈希表(散列表) 数组 + 链表 + 树
案例演示:
package com.qfedu;
public class Hero {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
//判断两个对象是否相等重写equals方法
// hero对象.equals(hero对象)
@Override
public boolean equals(Object obj) {
if(obj==null) {
return false;
}
if(this==obj) {
return true;
}
if(obj instanceof Hero) {
Hero hero = (Hero)obj;
if(this.getName().equals(hero.getName())) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return this.getId();
}
}
单独演示:泛型方法。
- 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步。
- 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表。
6.2.2 LinkedHashSet
- 链表实现的HashSet,按照链表进行存储,即可保留元素的插入顺序。
6.2.3 TreeSet
- 基于排列顺序实现元素不重复。
- 实现了SortedSet接口,对集合元素自动排序。
- 元素对象的类型必须实现Comparable接口,指定排序规则(自然排序)。
- 通过CompareTo方法确定是否为重复元素。
案例演示:使用TreeSet保存对象数据。
package com.qfedu;
import java.lang.ref.PhantomReference;
import java.util.SortedSet;
//用来测试TreeeSet
public class Hero1 implements Comparable<Hero1>{
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
//定义排序规则 hero.compareTO(hero)
//比较两个对象是否相乖,如果相等,返回0 大于返回1 小于返回-1
@Override
public int compareTo(Hero1 o) {
// 我的主键 > 你的主键
if(this.getId() > o.getId()) {
return 1;
}else if(this.getId() < o.getId()) {// 我的主键 < 你的主键
return -1;
}
return 0;
}
}
package com.qfedu;
import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
public class Test3 {
public static void main(String[] args) {
//1.创建TreeSet
TreeSet<Hero1> set = new TreeSet<Hero1>();
//2.创建Hero1对象
Hero1 hero1 = new Hero1();
hero1.setId(132);
hero1.setName("甄姬");
Hero1 hero2 = new Hero1();
hero2.setId(127);
hero2.setName("马可波罗");
Hero1 hero3 = new Hero1();
hero3.setId(110);
hero3.setName("甄姬");
set.add(hero1);
set.add(hero2);
set.add(hero3);
for (Hero1 hero11 : set) {
System.out.println(hero11);
}
}
}
注:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素。
Comparator接口:
- 比较器,实现定制比较。
- compare(o1,o2)方法的返回值0,表示重复。
案例演示:比较器的使用。
package com.qfedu;
import java.util.Comparator;
import java.util.TreeSet;
//利用比较器重新定义比较的规则
public class Test4 {
public static void main(String[] args) {
//TreeSet实例 的时候,重写比较方法 匿名内部类对象
//定义规则 0 == 1 > -1 <
//创建比较器对象
Comparator<Hero1> comparator = new Comparator<Hero1>() {
@Override
public int compare(Hero1 o1, Hero1 o2) {
//比较这两个对象 o1 o2 == null
if (o1.getId() > o2.getId()) {
return 1;
} else if (o1.getId() < o2.getId()) {
return -1;
}
return 0;
}
};
TreeSet<Hero1> set = new TreeSet(comparator);
//2.创建Hero1对象
Hero1 hero1 = new Hero1();
hero1.setId(132);
hero1.setName("甄姬");
Hero1 hero2 = new Hero1();
hero2.setId(127);
hero2.setName("马可波罗");
Hero1 hero3 = new Hero1();
hero3.setId(110);
hero3.setName("甄姬");
set.add(hero1);
set.add(hero2);
set.add(hero3);
for (Hero1 hero11 : set) {
System.out.println(hero11);
}
}
}
七、Map集合
Map接口的特点:
- 用于存储任意键值对(Key-Value)。
- 键:无下标、不可以重复(唯一)。
- 值:无下标、可以重复 。
7.1 Map接口
特点:
- 称为“映射”存储一对数据(Key-Value),键不可重复,值可以重复。
常用方法:
方法名 | 描述 |
---|---|
V put(K key,V value) | 将对象存入到集合中,关联键值。key重复则覆盖原值。 |
Object get(Object key) | 根据键获取对应的值。 |
Set keySet() | 返回所有key。 |
Collection values() | 返回包含所有值的Collection集合。 |
Set<Map.Entry<K,V>> entrySet() | 键值匹配的Set集合。 |
7.2 Map实现类
7.2.1 HashMap【重点】
- JDK1.2版本,线程不安全,运行效率快。
- 允许用null 作为key或是value。
- 存储结构:哈希表。
案例演示:HashMap保存对象数据。
package com.qfedu.map;
import com.qfedu.list.Course;
import com.qfedu.list.Stduent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test01 {
public static void main(String[] args) {
//1.创建map 对象 key, value
// 1001 张三
// 1002 李四
// 1003 王五
Map a = new HashMap();
//增
// key 键 唯一的
// value值
a.put(1001,"张三");
a.put(1002,"李四");
a.put(1003,"王五");
System.out.println(a);
System.out.println("=======里边有多少个元素");
System.out.println(a.size());
System.out.println("=====泛型");
// 泛型
Map<Integer,String> map = new HashMap<>();
map.put(1001,"张三");
map.put(1002,"李四");
map.put(1003,"王五");
map.put(1003, "王五");
System.out.println(map);
// 可以放对象
Map<String,Stduent> map1 = new HashMap();
Stduent s1 = new Stduent(1001,"小马");
Stduent s2 = new Stduent(1002,"小李");
Stduent s3 = new Stduent(1002,"小平");
map1.put("1",s1);
map1.put("2",s2);
map1.put("3",s3);
System.out.println(map1);
System.out.println("======map list");
//可以放List
//1.1号同学 选 2门 2号同学选3门课
Map< String, List<Course> > map2 = new HashMap<>();
//准备的课程
Course c1 = new Course(1,"java");
Course c2 = new Course(2,"如何重新做人");
Course c3 = new Course(3,"母鸡的产后护理");
//1号同学
List<Course> list1 = new ArrayList<>();
list1.add(c1);
list1.add(c2);
//2号同学
List<Course> list2 = new ArrayList<>();
list2.add(c1);
list2.add(c2);
list2.add(c3);
//把1号和2号添加到map
map2.put("1",list1);
map2.put("2",list2);
System.out.println(map2);
}
}
package com.qfedu;
import java.util.*;
public class Test5 {
public static void main(String[] args) {
// 1.key value 键值对 id=132 id:132
// 键 不可以重复
Map<String,String> map = new HashMap<String,String>();
//2.添加值
map.put("105","廉颇");
map.put("106","小乔");
map.put("107","赵云");
//3. 遍历
// 3. 获取key 的集合
Set<String> keys = map.keySet();
for (String key : keys) {
// 4.获取单个值 get(key的值 )
String s = map.get(key);
System.out.println(s);
}
// 3.2遍历方式二: Entry 条目
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key="+entry.getKey()+ " value="+entry.getValue());
}
// 收集所的value值 ,返回一个集合
Collection<String> values = map.values();
System.out.println("values="+values);
//有几条数据
int size = map.size();
//是否包含某个 key
boolean b = map.containsKey("106");
System.out.println("b==="+b);
// --value值可能是个集合
Map<String, List> map1 = new HashMap<>();
List list = new ArrayList();
map1.put("140000",list);
//value-- key -- value 主键--对象
Map<Integer,Hero> heroMap = new HashMap<>();
Hero hero = new Hero();
hero.setId(159);
hero.setName("小乔");
heroMap.put(hero.getId(), hero);
System.out.println(heroMap);
}
}
7.2.2 TreeMap
实现了SortedMap接口(Map的子接口),可以对key自动排序,Key需实现Comparable接口。
案例演示:使用TreeMap保存数据。
package com.qfedu;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Test6 {
public static void main(String[] args) {
TreeMap<Integer,Hero1> treeMap = new TreeMap<>();
Hero1 hero1 = new Hero1();
hero1.setId(114);
hero1.setName("刘禅");
Hero1 hero2 = new Hero1();
hero1.setId(115);
hero2.setName("阿斗");
treeMap.put(hero1.getId(),hero1);
Set<Integer> keys = treeMap.keySet();
for (Integer key : keys) {
System.out.println(treeMap.get(key));
}
Set<Map.Entry<Integer, Hero1>> entries = treeMap.entrySet();
for (Map.Entry<Integer, Hero1> entry : entries) {
Integer key = entry.getKey();
Hero1 value = entry.getValue();
}
}
}
7.2.3 其他实现类
Hashtable :
- JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
Properties :
- Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。