java集合框架详解
1. 什么是集合?
概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
和数组的区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
位置: java.util.*
2. Collection 体系集合
2.1 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()
//将此集合转换成数组。
iterator()
:对此集合的元素进行遍历。
2.2 Collection使用
使用字符串作为元素
package commonClass.stringClass;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* collection 的使用
* 1. 添加元素
* 2. 删除元素
* 3. 遍历元素
* 4. 判断
*/
public class TestCollection {
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("榴莲");
// System.out.println("删除之后" + collection.size());
// collection.clear();
// System.out.println("清空之后" + collection.size());
// 3. 遍历元素
// 3.1 使用增强for
System.out.println("===============使用增强for================");
for (Object o : collection) {
System.out.println(o);
}
// 3.2 使用迭代器(迭代器专门用来遍历集合的一种方式)
System.out.println("===============使用迭代器================");
// 有三个方法:
// hasNext(); 有没有下一个元素 (迭代时先执行)
// next(); 获取下一个元素
// remove(); 删除当前元素
Iterator it = collection.iterator(); // 返回类型是接口类型的
while (it.hasNext()){
String s = (String) it.next();
System.out.println(s);
//collection.remove(s); // 迭代过程中 不能使用collection删除方法, 但是可以用 it.remove();
//it.remove();
}
System.out.println("元素个数" + collection.size());
// 4. 判断
System.out.println(collection.contains("西瓜"));
System.out.println(collection.isEmpty());
}
}
使用类对象作为元素
package commonClass.stringClass;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 保存学生信息
*/
public class TestCollection02 {
public static void main(String[] args) {
// 新建collection对象
Collection collection = new ArrayList();
Student s1 = new Student("张三",10);
Student s2 = new Student("张无忌",28);
Student s3 = new Student("李四",50);
// 1. 添加数组
collection.add(s1);
collection.add(s2);
collection.add(s3);
collection.add(s3);
System.out.println("元素个数: "+ collection.size());
System.out.println(collection.toString());
// 2. 删除, 只是把集合中的地址删除了
//collection.remove(s3);
//collection.remove(new Student("李四",50)); 不能这样做,remove用的是equals比较
//collection.clear();
System.out.println("删除之后: "+ collection.size());
System.out.println(collection.toString());
// 3. 遍历
// 3.1 增强for
for (Object o : collection) {
Student s = (Student)o;
System.out.println(s.toString());
}
// 3.2 迭代器 hasNext() next() remove() ; 迭代过程中不能使用collection的删除方法
Iterator it = collection.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
// 4. 判断
System.out.println(collection.contains(s1));
System.out.println(collection.isEmpty());
}
}
3. List集合
3.1 List子接口
特点: 有序,有下表,元素可以重复
方法:
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接口使用1
package commonClass.stringClass;
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* List子接口的使用
* 特点: 有序,有下表,可以重复
*/
public class TestList {
public static void main(String[] args) {
// 创建集合对象
List list = new ArrayList<>();
// 1. 添加元素
list.add("苹果");
list.add("小米");
list.add(0,"华为");
System.out.println("元素个数:" + list.size());
System.out.println(list.toString());
//2. 删除元素;
// list.remove(0);
// list.remove("苹果");
// System.out.println("删除后:" + list.size());
// System.out.println(list.toString());
// 3. 遍历
// 3.1 使用for进行遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 3.2 使用增强for
for (Object o : list) {
System.out.println(o);
}
// 3.3 使用迭代器
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
// 3.4 使用列表迭代器, 和Iterator的区别 ListIterator可以向前向后遍历,添加,删除,修改元素
ListIterator lit = list.listIterator();
System.out.println("==============================3.4 使用列表迭代器,从前往后===================");
while (lit.hasNext()){
System.out.println(lit.nextIndex()+":"+lit.next());
}
System.out.println("==============================3.4 使用列表迭代器,从后往前===================");
while (lit.hasPrevious()){
System.out.println(lit.previousIndex()+":"+lit.previous());
}
// 4. 判断
System.out.println(list.contains("苹果"));
System.out.println(list.isEmpty());
// 5. 获取
System.out.println(list.indexOf("华为"));
}
}
3.3 List使用接口2
package commonClass.stringClass;
import java.util.ArrayList;
import java.util.List;
public class TestList02 {
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);
list.add(200);
System.out.println("元素个数:"+ list.size());
System.out.println(list.toString());
// 2. 删除操作
//list.remove(0);
//list.remove((Object) 20);
list.remove(new Integer(200));
System.out.println("删除元素:"+ list.size());
System.out.println(list.toString());
// 3. 补充方法 subList: 返回子集合; 含头不含尾
List subList = list.subList(1,3);
System.out.println(subList.toString());
}
}
4. List实现类
ArraysList【重点】:
- 数组结构实现,查询快、增删慢;
- JDK1.2版本,运行效率快、线程不安全;
Vector:
- 数组结构实现,查询快、增删慢;
- JDK1.2版本,运行效率慢、线程安全;
LinkedList:
- 链表结构实现,增删快,查询慢。
4.1 ArrayList使用
package commonClass.ArrayListDemo;
import commonClass.stringClass.Student;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
/**
* ArrayList的使用
* 存储结构: 数组,查找遍历快,增删慢
*/
public class ArrayListDemo {
public static void main(String[] args) {
// 创建集合
ArrayList arrayList = new ArrayList();
// 1. 添加元素
Student s1 = new Student("刘德华",20);
Student s2 = new Student("周杰论",25);
Student s3 = new Student("梁朝伟",56);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println("元素个数:" + arrayList.size());
System.out.println(arrayList.toString());
// 2. 删除元素
arrayList.remove(new Student("刘德华",20));
System.out.println("元素个数:" + arrayList.size());
// 重写类的equals方法
// @Override
// public boolean equals(Object o) {
// // 判断是不是同一对象
// if(this == o){
// return true;
// }
// if(o == null){ // 判断是否为空
// return false;
// }
// // 判断是否是student类型
// if(o instanceof Student){
// Student s = (Student) o;
// // 比较属性
// if(this.name.equals(s.getName()) && this.age == s.getAge()){
// return true;
// }
// }
// // 不满足返回false
// return false;
// }
// 3. 遍历元素
// 3.1 使用迭代器
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()){
Student s = (Student) iterator.next();
System.out.println(s.toString());
}
// 3.2 列表迭代器
ListIterator lit = arrayList.listIterator();
while (lit.hasNext()) {
System.out.println(lit.next().toString());
}
// 逆序
while(lit.hasPrevious()){
Student s = (Student) lit.previous();
System.out.println(s.toString());
}
// 4. 判断
System.out.println(arrayList.contains(s2));
System.out.println(arrayList.contains(new Student("刘德华",20)));
System.out.println(arrayList.isEmpty());
// 5. 查找
System.out.println(arrayList.indexOf(s3));
}
}
重写toString和equals方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
// 判断是不是同一对象
if(this == o){
return true;
}
if(o == null){ // 判断是否为空
return false;
}
// 判断是否是student类型
if(o instanceof Student){
Student s = (Student) o;
// 比较属性
if(this.name.equals(s.getName()) && this.age == s.getAge()){
return true;
}
}
// 不满足返回false
return false;
}
4.2 ArrayList源码分析
默认容量大小为10
注意:如果没有向集合中添加任何元素,容量为0
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
elementData,存放元素的数组
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
实际的元素个数
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
add添加元素,添加一个任意元素之后,容量10。扩容是原来的1.5倍
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
4.3 Vector类使用
数组结构,查询类、增删慢;
package commonClass.ArrayListDemo;
import java.util.Enumeration;
import java.util.Vector;
/**
* 演示vector集合的使用
* 存储结构: 数组
*/
public class VectorTest {
public static void main(String[] args) {
// 创建集合
Vector vector = new Vector();
vector.add("草莓");
vector.add("苹果");
vector.add("西瓜");
vector.add("梨");
System.out.println("元素个数"+ vector.size());
System.out.println(vector.toString());
// 2. 删除
// vector.remove(0);
// vector.remove("西瓜");
// vector.clear();
// 2. 遍历
// 使用枚举器
Enumeration en = vector.elements();
while (en.hasMoreElements()){
String o = (String) en.nextElement();
System.out.println(o);
}
// 4. 判断
System.out.println(vector.contains("西瓜"));
// 5. vector其他方法
// fitstElement, lastElement, elementAt();
}
}
4.4 LinkedList使用*
链表结构实现,增删快、查询慢
package commonClass.ArrayListDemo;
import commonClass.stringClass.Student;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
/**
* LinkedList的使用
* 存储结构: 双向链表
*/
public class LinkedListTest {
public static void main(String[] args) {
// 创建集合
LinkedList linkedList = new LinkedList();
// 1. 添加元素
Student s1 = new Student("刘德华",20);
Student s2 = new Student("周杰论",25);
Student s3 = new Student("梁朝伟",56);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s3);
System.out.println("元素个数: " + linkedList.size());
System.out.println(linkedList.toString());
System.out.println(linkedList);
// 2. 删除元素
// linkedList.remove(s1);
// linkedList.remove(new Student("刘德华",20));
// System.out.println("元素个数: " + linkedList.size());
// 3. 遍历
// 3.1 for
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
// 3.2 增强for
for (Object o : linkedList) {
Student s = (Student)o; //强制类型转换,因为放进去后 就变成object类型了
System.out.println(s.toString());
}
// 3.3 迭代器
System.out.println("====================迭代器");
Iterator it = linkedList.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
System.out.println("====================列表迭代器");
ListIterator lit = linkedList.listIterator();
while (lit.hasNext()){
Student s = (Student)lit.next();
System.out.println(s );
}
// 4判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
// 5 获取
System.out.println(linkedList.indexOf(s1));
}
}
4.5 LinkedList源码分析
item 实际数据
next 下一个节点
prev 前一个节点
4.6 ArrayList和LinkedList区别
5. 泛型
Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
常见形式有泛型类、泛型接口、泛型方法。
语法:
·〈T,…>T称为类型占位符,表示一种引用类型。
好处:
·(1)提高代码的重用性
·(2)防止类型转换异常,提高代码的安全性
5.1 泛型类
package commonClass.MyGeneric;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类来创建对象
// 注意 1 泛型只能使用引用类型 2. 不同泛型对象之间不能相互复制
MyGeneric<String > myGeneric = new MyGeneric<String>();
myGeneric.t = "hello";
myGeneric.show("大家好!!");
String t = myGeneric.getT();
MyGeneric<Integer> myGeneric1 = new MyGeneric<Integer>();
myGeneric1.t = 100;
myGeneric1.show(200);
Integer integer = myGeneric1.getT();
}
}
package commonClass.MyGeneric;
/**
* 泛型类
* 语法: 类名<T,E>
* T类型占位符,表示一种引用类型,如果编写多个使用逗号隔开
*/
public class MyGeneric<T> {
// 使用泛型T
// 1. 创建变量
T t ;
// 2. 添加一个方法,作为方法的参数
public void show(T t){
// 不能new对象,实例化。
System.out.println(t);
}
// 3. 泛型作为方法的返回值
public T getT(){
return t;
}
}
5.2 泛型接口
实现类时确实类型
package commonClass.MyGeneric;
public class MyInterfacempl implements MyInterface<String>{ // 实现接口,泛型类要具体
@Override
public String server(String s) {
System.out.println(s);
return s;
}
}
实现类时不确实类型
package commonClass.MyGeneric;
// 实现接口时不确定
public class MyInterfaceImpl2<T> implements MyInterface<T>{
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
测试
package commonClass.MyGeneric;
public class TestGeneric {
public static void main(String[] args) {
System.out.println("===================================");
MyInterfacempl impl = new MyInterfacempl();
impl.server("xxxxxxxxxxxxxxxx");
MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<>();
impl2.server(1000);
}
}
5.3 泛型方法
package commonClass.MyGeneric;
/**
* 泛型方法
* 语法 : <T> 返回值类型
*
*/
public class MyGenericMethod {
// 泛型方法
public <T> T show(T t){
System.out.println("泛型方法"+t);
return t;
}
}
package commonClass.MyGeneric;
public class TestGeneric {
public static void main(String[] args) {
// 泛型方法调用
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("string hahaha ni shi shui wo sh");
myGenericMethod.show(200);
myGenericMethod.show(3.14);
}
}
5.4 泛型集合
·概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
·特点:
·编译时即可检查,而非运行时抛出异常。
·访问时,不必类型转换(拆箱)。
·不同泛型之间引用不能相互赋值,泛型不存在多态。
package commonClass.MyGeneric;
import commonClass.stringClass.Student;
import oop.demo08.A;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo3 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("xxx");
arrayList.add("xxx");
// arrayList.add(10);
for (String s : arrayList) {
System.out.println(s);
}
ArrayList<Student> arrayList1 = new ArrayList<>();
commonClass.stringClass.Student s1 = new commonClass.stringClass.Student("刘德华",20);
commonClass.stringClass.Student s2 = new commonClass.stringClass.Student("周杰论",25);
commonClass.stringClass.Student s3 = new commonClass.stringClass.Student("梁朝伟",56);
arrayList1.add(s1);
arrayList1.add(s2);
arrayList1.add(s1);
arrayList1.add(s1);
Iterator<Student> it = arrayList1.iterator();
while (it.hasNext()){
Student s = it.next();
System.out.println(s.toString());
}
}
}
6. Set集合
Set子接口: 无序、无下标、元素不可重复。
package commonClass.MySet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* 测试set接口的使用
*特点: 无序, 无下标, 元素不可重复
*/
public class MySet {
public static void main(String[] args) {
// 创建集合
Set<String> set = new HashSet<>();
// 1. 添加数据
set.add("小米");
set.add("苹果");
set.add("华为");
System.out.println("数据个数+"+set.size());
System.out.println(set.toString());
// 2. 删除
set.remove("小米");
System.out.println("数据个数+"+set.size());
// 3. 遍历 重点
// 3.1 使用增强for
for (String s : set) {
System.out.println(s);
}
// 3.2 使用迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
// 4. 判断
System.out.println(set.contains("华为"));
System.out.println(set.isEmpty());
}
}
6.1 HashSet使用
·HashSet【重点】:
·基于HashCode计算元素存放位置。
·当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
package commonClass.MySet;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
*/
public class MyHashSet {
public static void main(String[] args) {
// 新建集合
HashSet<String> hashSet = new HashSet<>();
// 1. 添加元素
hashSet.add("刘德华");
hashSet.add("梁朝伟");
hashSet.add("周润发");
hashSet.add("林志玲");
//hashSet.add("林志玲");
System.out.println(hashSet.size());
System.out.println(hashSet.toString());
// 2. 删除数据
// hashSet.remove("刘德华");
// System.out.println(hashSet.toString());
// 3. 遍历
System.out.println("==================增强for");
for (String s : hashSet) {
System.out.println(s);
}
System.out.println("==================Iterator");
Iterator<String> it = hashSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
// 4. 判断
System.out.println(hashSet.contains("郭富城"));
System.out.println(hashSet.isEmpty());
}
}
6.2 HashSet使用(2)
package commonClass.MySet;
import java.util.HashSet;
public class MyHashSet02 {
public static void main(String[] args) {
// 创建集合
HashSet<Person> persons = new HashSet<>();
// 1. 添加数据
Person p1 = new Person("刘德华“", 50);
Person p2 = new Person("周润发“", 501);
Person p3 = new Person("周杰林“", 22);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(new Person("周杰林“", 22));
System.out.println("元素个数:" + persons.size());
System.out.println(persons.toString());
// 2. 删除操作
persons.remove(p1);
persons.remove(new Person("周杰林“", 22));
System.out.println("删除之后:" + persons.size());
// 3. 遍历 重点
// 3.1 增强for
for (Person person : persons) {
System.out.println(person.toString());
}
System.out.println("==============================");
// 3.2 迭代器
Iterator it = persons.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
// 4. 判断
System.out.println(persons.contains(p1));
System.out.println(persons.isEmpty());
}
}
6.3 HashSet存储方式
存储过程:
- 根据hashcode,计算保存的位置;如果此位置为空,则直接保存,若不为空,执行第二步。
- 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
person,重写了hashcode和equals方法
package commonClass.MySet;
import java.util.Objects;
/**
* 人类
*/
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = 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 ) return false;
if( o instanceof Person){
Person person = (Person) o;
if(this.name.equals(person.getName()) && this.age == person.getAge()){
return true;
}
}
return false;
}
@Override
public int hashCode() {
int n1 = this.name.hashCode();
int n2 = this.age;
return n1 + n2;
}
}
6.4 HashSet补充
31
(1)31是一个质数,减少散列冲突
(2)31能够提高执行效率 31*i = (i<<5)-i
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
6.5 TreeSet概述
基于排列顺序实现元素不重复。
实现了SortedSet接口,对集合元素自动排序。
元素对象的类型必须实现Comparable接口,指定排序顺序。
通过CompareTo方法确定是否为重复元素。
6.6 TreeSet的使用
package commonClass.MySet;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用
* 存储结构: 红黑树
*/
public class MyTreeSet {
public static void main(String[] args) {
// 1. 创建集合
TreeSet<String> treeSet = new TreeSet<>();
// 1. 添加元素
treeSet.add("xyz");
treeSet.add("abc");
treeSet.add("hello");
treeSet.add("xyz");
System.out.println("打印元素个数:" + treeSet.size());
System.out.println(treeSet.toString());
// 2. 删除元素
treeSet.remove("xyz");
System.out.println("打印元素个数:" + treeSet.size());
System.out.println(treeSet.toString());
// 3. 遍历
// 3.1 增强for
for (String s : treeSet) {
System.out.println(s);
}
// 3.2 iter
Iterator it = treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
// 4. 判断
System.out.println(treeSet.contains("abd"));
}
}
不能正常添加元素。因为TreeSet要求根据某一指标的数值大小才能存放数据。
因为类没有标准,得告诉treeset怎么比
在person类中,实现Comparable接口,重写比较方法,
public class Person implements Comparable<Person>{
private String name;
private int age;
// 先按姓名来比,然后按年龄比
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());//字符串有comparaTo方法的
int n2 = this.age-o.getAge();
return n1 == 0 ? n2 : n1;
}
package commonClass.MySet;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 使用TreeSet保存数据
* 要求: 元素必须要实现Comparable类,compareTo()方法返回值为0,认为是重复元素
*/
public class MyTreeSet02 {
public static void main(String[] args) {
// 创建集合
TreeSet<Person> person = new TreeSet<>();
// 1. 添加元素
Person p1 = new Person("刘德华", 20);
Person p2 = new Person("周杰伦", 23);
Person p3 = new Person("王祖蓝", 24);
person.add(p1);
person.add(p2);
person.add(p3);
System.out.println("元素个数: " + person.size());
System.out.println(person.toString());
// 2. 删除
person.remove(p1);
person.remove(new Person("王祖蓝", 24)); // 实现了compara接口,所以能删除
System.out.println("元素个数: " + person.size());
// 3. 遍历
// 3.1 增强for
for (Person person1 : person) {
System.out.println(person1);
}
// 3.2 迭代器
Iterator<Person> ite = person.iterator();
while (ite.hasNext()){
System.out.println(ite.next());
}
// 4. 判断
System.out.println(person.contains(p1));
}
}
6.7 Comparator接口
Comparator: 实现定制比较(比较器)
package commonClass.MySet;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet集合的使用
* Comparator: 实现定制比较(比较器)
* Comparable: 可比较的
*/
public class MyTreeSet03 {
public static void main(String[] args) {
// 创建一个集合 使用了匿名内部类, 指定比较规则
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
@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;
}
});
// 1. 添加元素
Person p1 = new Person("x", 20);
Person p2 = new Person("t", 23);
Person p3 = new Person("a", 24);
Person p4 = new Person("b", 24);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println(persons.toString());
}
}
6.8 TreeSet案例
package commonClass.MySet;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 使用Treeset集合 实现字符串按照长度进行排序
*
*/
public class MyTreeSet04 {
public static void main(String[] args) {
// 创建集合并指定比较规则, treeset不需要重写equals和hashcode
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length() - o2.length();
int n2 = o1.compareTo(o2);
return n1 == 0? n2: n1;
}
});
// 添加数据
treeSet.add("hello");
treeSet.add("hell");
treeSet.add("hel");
treeSet.add("ho");
treeSet.add("zhangsan");
treeSet.add("cat");
treeSet.add("nanjing");
System.out.println(treeSet.toString());
System.out.println("元素个数:"+ treeSet.size());
}
}
7. Map集合概述
·特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复。
·方法:
V put(K key,V value)
将对象存入到集合中,关联键值。key重复则覆盖原值。
Object get(Object key)
根据键获取对应的值。
Set<K> keySet();
返回所有key。
Collection<V> values()
返回包含所有值的Collection集合。
Set<Map.Entry<K,V>>
键值匹配的Set集合。
7.1 Map接口使用
package commonClass.MyMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Map接口的使用
* 特点:1. 存储键值对 2. 键不能重复 3. 无序
*/
public class MyMap01 {
public static void main(String[] args) {
// 创建Map集合
Map<String,String> map = new HashMap<>();
// 1. 添加元素
map.put("cn","中国");
map.put("usa","美国");
map.put("uk","英国");
map.put("cn", "zhongguo"); // 添加重复key, value会更新
System.out.println("元素个数:" + map.size());
System.out.println(map.toString());
// 2. 删除
map.remove("usa");
System.out.println(map.toString());
// 3. 遍历
// 3.1 使用keySet() 返回值是所有key的set集合
Set<String> keyset = map.keySet();
for (String s : keyset) {
System.out.println(s + "-----------" + map.get(s));
}
for (String s : map.keySet()) {
System.out.println(s + "-----------" + map.get(s));
}
// 3.2 使用entrySet()方法
Set<Map.Entry<String ,String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+"------------" + entry.getValue());
}
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey()+"------------" + entry.getValue());
}
// 4. 判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("cn"));
}
}
7.2 HashMap的使用
HashMap【重点】:
JDK1.2版本,线程不安全,运行效率快;允许用nul1作为key或是value。
package commonClass.MyMap;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.PatternSyntaxException;
/**
* HashMap的使用
* 存储结构:哈希表(数值+ 链表 + 红黑树)
* 使用key的hashcode和equals作为重复
*/
public class MyHashMap {
public static void main(String[] args) {
// 创建集合
HashMap<Student,String> students = new HashMap<>();
// 刚创建Mashmap之后,没有添加元素 table = null, size= 0
// 目的节省空间
// 添加元素
Student s1 = new Student("孙悟空",100);
Student s2 = new Student("猪八戒",101);
Student s3 = new Student("沙僧",103);
students.put(s1,"北京");
students.put(s2,"上海");
students.put(s3,"东海");
students.put(s3,"南京");
students.put(new Student("沙僧",103),"南京"); // 重写hashcode和equals方法,就可以添加进来
System.out.println("元素个数:" + students.size());
System.out.println(students.toString());
// 2. 删除
students.remove(s1);
System.out.println("删除之后:" + students.size());
// 3. 遍历
// 3.1 使用keySet();
for (Student student : students.keySet()) {
System.out.println(student.toString() + "---" + students.get(student));
}
// 3.2 使用entrySet();
for (Map.Entry<Student, String> entry : students.entrySet()) {
System.out.println(entry.getKey()+ "======" + entry.getValue());
}
// 4. 判断
System.out.println(students.containsKey(s1));
System.out.println(students.containsKey(new Student("沙僧",103)));
}
}
package commonClass.MyMap;
import java.util.Objects;
public class Student {
private String name;
private int stuNo;
public Student() {
}
public Student(String name, int stuNo) {
this.name = name;
this.stuNo = stuNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getStuNo() {
return stuNo;
}
public void setStuNo(int stuNo) {
this.stuNo = stuNo;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", stuNo=" + stuNo +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return stuNo == student.stuNo && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, stuNo);
}
}
7.3 HashMap源码分析
jdk 1.8
当链表长度大于8,并且这个数组的长度大于64,就会把链表调整为红黑树。
刚创建Mashmap之后,没有添加元素 table = null, size= 0
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
当添加第一个元素时,数组容量为16
(1)HashMap刚创建时,table是null,为了节省空间,当添加第一个元素是,table容量调整为16
(2)当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数。
(3)jdk1.8当每个链表长度大于8,并且元素个数大于等于64时,会调整为红黑树,目的提高执行效率
(4)jdk1.8当链表长度小于6时,调整成链表
(5)jdk1.8以前,链表时头插入,jdk1.8以后时是尾插入
7.4 Hashtable和Properies
7.5 TreeMap的使用
package commonClass.MyMap;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
/**
* TreeMap的使用
* 存储结构: 红黑树
*/
public class MyTreeMap {
public static void main(String[] args) {
// 新建集合(定制比较)
TreeMap<Student, String> treeMap = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return 0;
}
});
// 1. 添加元素
Student s1 = new Student("孙悟空",100);
Student s2 = new Student("猪八戒",101);
Student s3 = new Student("沙僧",103);
treeMap.put(s1, "北京");
treeMap.put(s2, "上海");
treeMap.put(s3, "南京");
treeMap.put(new Student("沙僧",103), "南京");
System.out.println(treeMap.size());
System.out.println(treeMap.toString());
// 2. 删除
treeMap.remove(s3);
System.out.println(treeMap.toString());
// 3. 遍历
// 3.1 使用keySet
for (Student student : treeMap.keySet()) {
System.out.println(student + "=======" + treeMap.get(student));
}
// 3.2 使用entryset
for (Map.Entry<Student, String> studentStringEntry : treeMap.entrySet()) {
System.out.println(studentStringEntry.getKey()+studentStringEntry.getValue());
}
// 4. 判断
System.out.println(treeMap.containsKey(s1));
}
}
8. Collections工具类
·概念:集合工具类,定义了除了存取以外的集合常用方法。
·方法:
public static void reverse(List<?>list)
反转集合中元素的顺序
public static void shuffle(List<?>list)
随机重置集合元素的顺序
public static void sort(List<T>list)
升序排序(元素类型必须实现
Comparable接口)
package commonClass.MyMap;
import java.util.*;
public class MyCollection {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(10);
list.add(30);
list.add(2);
list.add(6);
// sort 排序
System.out.println(list.toString());
Collections.sort(list);
System.out.println(list.toString());
Collections.sort(list);
// binarySearch 二分查找
int a = Collections.binarySearch(list,12);
int b = Collections.binarySearch(list,20);
System.out.println(a);
System.out.println(b);
// copy 复制
List<Integer> dest = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
dest.add(0);
}
Collections.copy(dest, list);
System.out.println(dest.toString());
// reverse 反转
Collections.reverse(list);
System.out.println("反转之后"+ list.toString());
// shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后"+ list.toString());
// 补充: list转成 数组
System.out.println("==========list转成 数组============");
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
// 数组转成集合
System.out.println("==========数组转成集合============");
String[] name = {"张三","李四","王五"};
List<String> list2 = Arrays.asList(name);
// 集合是受限集合,不能添加和删除
System.out.println(list2.toString());
System.out.println(list2);
// 把基本类型数组 转成集合时, 需要修改为包装类
// int[] nums = {54,123,564,6,132,132,56,4,3,4,6};
// List<int[]> list3 = Arrays.asList(nums);
Integer[] nums = {54,123,564,6,132,132,56,4,3,4,6};
List<Integer> list3 = Arrays.asList(nums);
System.out.println(list3);
}
}