集合框架
集合
什么是集合?
- 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
- 和数组区别:
- (1)数组长度固定,集合长度不固定
- (2)数组可以存储基本类型和引用类型,集合只能存储引用类型
- 位置:java.util.*;
Collection体系集合
- Interface Collection:该体系结构的根接口,代表一组对象,称为“集合”。
- List接口的特点:有序、有下标、元素可重复
- Set接口的特点:无序、无下标、元素不能重复
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.aggregation.demo01; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * Collection接口的使用 * (1)添加元素 * (2)删除元素 * (3)遍历元素 * (4)判断 * @author 大白很白 */ 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("------------------3.1 使用增强for-----------------------"); for (Object object : collection){ System.out.println((String) object); } //3.2 使用迭代器(迭代器专门用来遍历集合的一种方式) //hasNext();有没有下一个元素 //next();获取下一个元素 //remove();删除当前元素 System.out.println("------------------3.2 使用增强for-----------------------"); Iterator it = collection.iterator(); while(it.hasNext()){ String s = (String) it.next(); System.out.println(s); // collection.remove(s);//不能在迭代器内使用collection.remove()方法,不可并发修改 //it.remove(); } System.out.println("元素个数:"+collection.size());//元素个数:0 //(4)判断 System.out.println(collection.contains("西瓜")); System.out.println(collection.isEmpty()); } }
-
Collection的使用:保存学生信息
Student.java
package com.aggregation.demo01; /** * 学生类 * @ author 大白很白 */ public class Student { private String name; private int age; public Student(){ } public Student(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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Demo02.java
package com.aggregation.demo01; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * Collection的使用:保存学生信息 * @ author 大白很白 */ public class Demo02 { public static void main(String[] args) { //新建Collection对象 Collection collection = new ArrayList(); Student s1 = new Student("张三",16); Student s2 = new Student("李四",20); Student s3 = new Student("小王",18); //1添加数据 collection.add(s1); collection.add(s2); collection.add(s3); System.out.println("元素个数:"+collection.size()); System.out.println(collection.toString()); //2删除 collection.remove(s1); //collection.clear();//清除集合中的元素,集合中保存的实际是对象的地址,对象和集合之间指针指向 //System.out.println("删除之后:"+collection.size()); //3遍历 //3.1 增强for System.out.println("------------------3.1 增强for-------------------------"); for ( Object object:collection) { Student s = (Student)object; 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()); } }
-
迭代器
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之间的集合元素
package com.aggregation.demo01; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** * List子接口的使用 * 特点:1 有序 有下表 2 可以重复 * @ author 大白很白 */ 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());//删除之后:3 System.out.println(list.toString());//[华为, 苹果, 小米] //3遍历 //3.1使用for遍历 System.out.println("---------------------3.1使用for遍历-----------------------"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); /* 华为 苹果 小米 */ } //3.2使用增强for System.out.println("---------------------3.2使用for遍历-----------------------"); for (Object object:list) { System.out.println(object); /* 华为 苹果 小米 */ } //3.3使用迭代器 System.out.println("---------------------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()); /* 0:华为 1:苹果 2:小米 */ } System.out.println("---------------------3.4使用列表迭代器从后往前-----------------------"); while(lit.hasPrevious()){ System.out.println(lit.previousIndex()+":"+lit.previous()); /* 2:小米 1:苹果 0:华为 */ } //4判断 System.out.println(list.contains("苹果"));//true System.out.println(list.isEmpty());//false //5获取位置 System.out.println(list.indexOf("华为"));//0 } }
-
list添加数字数据
package com.aggregation.demo01; import java.util.ArrayList; import java.util.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(0); //list.remove(new Integer(20));//(Object)20 System.out.println("删除元素:"+list.size());//删除元素:5 System.out.println(list.toString());//[20, 30, 40, 50, 60] //3补充方法subList:返回子集合,含头不含尾 List subList = list.subList(1, 3); System.out.println(subList.toString());//[30, 40] } }
-
List实现类
- ArrayList【重点】:
- 数组结构实现,查询快、增删慢;
- JDK1.2版本,运行效率快、线程不安全。
- Vector:
- 数组结构实现,查询快、增删慢;
- JDK1.0版本,运行效率慢、线程安全。
- LinkedList:
- 链表结构实现,增删快,查询慢。
- 链表:!
ArrayList的使用
-
Student.java 重写了equals方法
package com.aggregation.demo01; /** * 学生类 * @ author 大白很白 */ public class Student { private String name; private int age; public Student(){ } public Student(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 "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object obj) { //1判断是否为同一个对象 if (this==obj) { return true; } //2判断是否为空 if (obj==null){ return false; } //3判断是否是Student类型 if (obj instanceof Student){ Student s = (Student)obj; //比较属性 if (this.name.equals(s.getName())&&this.age==s.getAge()){ return true; } } //5不满足条件返回false return false; } }
-
ArrayList的使用
package com.aggregation.demo01; import java.util.ArrayList; import java.util.Iterator; import java.util.ListIterator; /** * ArrayList的使用 * 存储结构:数组,查找遍历速度快,增删慢 */ public class Demo05 { public static void main(String[] args){ //1添加元素 ArrayList<Object> arrayList = new ArrayList<>(); Student s1 = new Student("王德发",20); Student s2 = new Student("光头强",22); Student s3 = new Student("赵四",18); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); System.out.println("元素个数:"+arrayList.size());//元素个数:3 System.out.println(arrayList.toString());//[Student{name='王德发', age=20}, Student{name='光头强', age=22}, // Student{name='赵四', age=18}] //2删除元素 //arrayList.remove(s1); //arrayList.remove(new Student("王德发",20));//重写了equals方法 //System.out.println("删除之后:"+arrayList.size());//删除之后:2 //3遍历元素【重点】 //3.1使用迭代器 System.out.println("-------------3.1使用迭代器------------------"); Iterator<Object> it = arrayList.iterator(); while(it.hasNext()){ Student s = (Student) it.next(); System.out.println(s.toString()); /* Student{name='王德发', age=20} Student{name='光头强', age=22} Student{name='赵四', age=18} */ } //3.2列表迭代器 System.out.println("-------------3.2使用列表迭代器------------------"); ListIterator<Object> lit = arrayList.listIterator(); while(lit.hasNext()){ Student s = (Student) lit.next(); System.out.println(s.toString()); /* Student{name='王德发', age=20} Student{name='光头强', age=22} Student{name='赵四', age=18} */ } System.out.println("-------------3.2使用列表迭代器逆序------------------"); while(lit.hasPrevious()){ Student s = (Student) lit.previous(); System.out.println(s.toString()); /* Student{name='赵四', age=18} Student{name='光头强', age=22} Student{name='王德发', age=20} */ } //4判断 // System.out.println(arrayList.contains(s1)); System.out.println(arrayList.contains(new Student("光头强",22)));//true,重写了equals方法 System.out.println(arrayList.isEmpty());//false //5查找 //System.out.println(arrayList.indexOf(s1)); System.out.println(arrayList.indexOf(new Student("赵四",18)));//2 } }
ArrayList源码分析
源码分析:DEFAULT_CAPACITY = 10; 默认容量
注意:如果没有向集合中添加任何元素时,容量为0;添加一个元素后,容量为10
每次扩容的大小为原来的1.5倍
EMPTY_ELEMENTDATA = {}; 存放元素的数组
size 实际元素个数(<=容量)
add() 添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
Vector集合的使用
package com.aggregation.demo02;
import java.util.Enumeration;
import java.util.Vector;
/**
* 演示Vector集合的使用
* 存储结构:数组
* @author 大白很白
*/
public class Demo01 {
public static void main(String[] args) {
//1创建集合
Vector vector = new Vector();
//添加元素
vector.add("草莓");
vector.add("芒果");
vector.add("西瓜");
System.out.println("元素个数:"+vector.size());
//2删除
//vector.remove(0);
//vector.remove("西瓜");
//vector.clear();
//3遍历
//使用枚举器
Enumeration en = vector.elements();
while (en.hasMoreElements()){
String o = (String) en.nextElement();
System.out.println(o);
}
//4判断
System.out.println(vector.contains("西瓜"));
System.out.println(vector.isEmpty());
//5 vector其他方法
//firstElement、lastElement、elementAt();
}
}
LinkedList的使用
package com.aggregation.demo02;
import com.aggregation.demo01.Student;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
/**
* LinkedList的使用
* 存储结构:双向链表
* @author 大白很白
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
LinkedList<Object> 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(s1);
//System.out.println("删除之后:"+linkedList.size());
//linkedList.clear();
//3遍历
//3.1for遍历
System.out.println("--------------for------------");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
//3.2增强for
System.out.println("--------------增强for-------------");
for (Object object:linkedList) {
Student s = (Student) object;
System.out.println(s.toString());
}
//3.3使用迭代器
System.out.println("--------------使用迭代器-------------");
Iterator<Object> it = linkedList.iterator();
while (it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.toString());
}
//3.4使用列表迭代器
System.out.println("--------------使用列表迭代器-------------");
ListIterator<Object> listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
Student s = (Student) listIterator.next();
System.out.println(s.toString());
}
//4判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
//5获取
System.out.println(linkedList.indexOf(s1));//下标0
}
}
LinkedList源码分析
Node first;链表的头节点
Node last;链表的尾节点
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
ArrayList和LinkedList区别
LinkedList 双向链表 或从尾到头
ArrayList:必须开辟连续空间,查询快,增删慢。
LinkedList:无需开辟连续空间,查询慢,增删快。
泛型
- Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
- 常见形式有泛型类、泛型接口、泛型方法。
- 语法:
- <T,...>T称为类型占位符,表示一种引用类型。
- 好处:
- (1)提高代码的重用性
- (2)防止类型转换异常,提高代码的安全性
泛型类
MyGeneric.java
package com.aggregation.demo02;
/**
* 泛型类
* 语法:类名<T>
* T是类型占位符,表示一种引用类型,如果编写多个,使用逗号隔开
* @author 大白很白
*/
public class MyGeneric<T> {
//使用泛型T
//1创建变量
T t;
//2泛型作为方法的参数
public void show(T t){
System.out.println(t);
}
//3使用泛型作为方法的返回值
public T getT(){
return t;
}
}
TestGeneric.java
package com.aggregation.demo02;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//注意:1泛型只能使用引用类型,2不同泛型对象之间不能相互复制
MyGeneric<String> myGeneric = new MyGeneric<String>();//后面的String可写可不写,JDK1.7之前必须写
myGeneric.t="hello";
myGeneric.show("大家好,加油");
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric2 = new MyGeneric<>();
myGeneric2.t=100;
myGeneric2.show(200);
Integer integer = myGeneric2.getT();
}
}
泛型接口
MyInterface.java
package com.aggregation.demo02;
/**
* 泛型接口
* 语法:接口名<T>
* 注意:不能创建泛型静态常量
* @author 大白很白
* @param <T>
*/
public interface MyInterface<T> {
String name="罗小通";
T server(T t);
}
MyInterfaceImpl.java
package com.aggregation.demo02;
public class MyInterfaceImpl implements MyInterface<String>{//泛型需设置一个类型
@Override
public String server(String t) {
System.out.println(t);
return t;
}
}
MyInterfaceImpl2.java
package com.aggregation.demo02;
public class MyInterfaceImpl2<T> implements MyInterface<T> {//暂未指定类型,可使用时再指定
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
TestMyInterface.java
package com.aggregation.demo02;
public class TestMyInterface {
public static void main(String[] args) {
MyInterfaceImpl impl1 = new MyInterfaceImpl();
impl1.server("你充q币吗");
MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<>();
impl2.server(1000);
}
}
泛型方法
MyGenericMethod.java
package com.aggregation.demo02;
/**
* 泛型方法
* 语法:<T>返回值类型
* @author 大白很白
*/
public class MyGenericMethod {
//泛型方法
public <T> T show(T t){
System.out.println("泛型方法:"+t);
return t;
}
}
TestMyGenericMethod
package com.aggregation.demo02;
public class TestMyGenericMethod {
public static void main(String[] args) {
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("加油加油!");//泛型方法:加油加油!
myGenericMethod.show(200);//泛型方法:200
myGenericMethod.show(3.14);//泛型方法:3.14
}
}
泛型集合
-
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
-
特点:
- 编译时即可检查,而非运行时抛出异常。
- 访问时,不必类型转换(拆箱)。
- 不同泛型之间引用不能相互赋值,泛型不存在多态。
package com.aggregation.demo02; import com.aggregation.demo01.Student; import java.util.ArrayList; import java.util.Iterator; public class Demo03 { public static void main(String[] args) { ArrayList<Student> arrayList = new ArrayList<Student>(); Student s1 = new Student("王德发",20); Student s2 = new Student("光头强",22); Student s3 = new Student("赵四",18); arrayList.add(s1); arrayList.add(s2); arrayList.add(s3); Iterator<Student> it = arrayList.iterator(); while (it.hasNext()){ Student s = it.next(); System.out.println(s.toString()); } } }
Set子接口
- 特点:无序、无下标、元素不可重复。
- 方法:全部继承自Collection中的方法。
Set实现类
- HashSet【重点】:
- 基于HashCode实现元素不重复。
- 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入。
- TreeSet:
- 基于排列顺序实现元素不重复。
- 实现了SortedSet接口,对集合元素自动排序。
- 元素对象的类型必须实现Comparable接口,指定排序规则。
- 通过ComparaTo方法确定是否为重复元素。
Set接口的使用
package com.aggregation.demo03;
import java.util.HashSet;
import java.util.Iterator;
/**
* 测试Set接口的使用
* 特点:(1)无序、没有下标 (2)不能重复
* @大白很白
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
HashSet<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.toString());
//3遍历【重点】
//3.1增强for
System.out.println("-------------增强for--------");
for (String string:set) {
System.out.println(string);
}
//3.2使用迭代器
System.out.println("-----------使用迭代器-------------");
Iterator<String> it = set.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(set.contains("华为"));
System.out.println(set.isEmpty());
}
}
HashSet的使用
Demo02
package com.aggregation.demo03;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* @ author 大白很白
*/
public class Demo02 {
public static void main(String[] args) {
//新建集合
HashSet<String> hashSet = new HashSet<>();
//1添加元素
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.size());
//3遍历操作
//3.1增强for
System.out.println("------------3.1增强for----------");
for (String string:hashSet) {
System.out.println(string);
}
//3.2使用迭代器
System.out.println("-------------3.2使用迭代器---------------");
Iterator<String> it = hashSet.iterator();
while (it.hasNext()){
//String s = it.next();
//System.out.println(s);
System.out.println(it.next());
}
//4判断
System.out.println(hashSet.contains("老兰"));
System.out.println(hashSet.isEmpty());
}
}
Demo03.java
package com.aggregation.demo03;
import java.util.HashSet;
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* @author 大白很白
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet<Person> persons = new HashSet<>();
//1添加数据
Person p1 = new Person("小红",18);
Person p2 = new Person("小绿",19);
Person p3 = new Person("小黑",20);
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
}
}
Person.java
package com.aggregation.demo03;
/**
* 人类
* @author 大白很白
*/
public class Person {
private String name;
private int 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;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
HashSet存储方式
存储过程
- 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
- 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
手动重写hashcode和equals
package com.aggregation.demo03;
/**
* 人类
* @author 大白很白
*/
public class Person {
private String name;
private int 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;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int hashCode() {
int n1=this.name.hashCode();
int n2=this.age;
return n1+n2;
}
@Override
public boolean equals(Object obj) {
if (this==obj){
return true;
}
if (obj==null){
return false;
}
if (obj instanceof Person){
Person p = (Person)obj;
if (this.name.equals(p.getName())&&this.age==p.getAge()){
return true;
}
}
return false;
}
}
使用快捷键重写hashcode和equals:Alt+Insert
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return getAge() == person.getAge() && Objects.equals(getName(), person.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
理解存储过程(重复判断依据)
package com.aggregation.demo03;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 存储过程
* 1. 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
* 2. 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
* @author 大白很白
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet<Person> persons = new HashSet<>();
//1添加数据
Person p1 = new Person("小红",18);
Person p2 = new Person("小绿",19);
Person p3 = new Person("小黑",20);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(new Person("小红",18));//重写了hashcode,equals
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
//2删除操作
//persons.remove(p1);
//persons.remove(new Person("小红",18));
//System.out.println("删除之后:"+persons.size());
//3遍历【重点】
//3.1使用增强for
for (Person person:persons) {
System.out.println(person.toString());
}
//3.2使用迭代器
System.out.println("--------------------------");
Iterator<Person> it = persons.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(persons.contains(new Person("小黑",20)));
System.out.println(persons.isEmpty());
}
}
TreeSet的使用
存储String类型
Demo04.java
package com.aggregation.demo03;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用
* 存储结构:红黑树
* @author 大白很白
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
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.toString());
//3遍历
//3.1增强for
System.out.println("------------------------");
for (String string:treeSet) {
System.out.println(string);
}
//3,2使用迭代器
System.out.println("-----------------------");
Iterator<String> it = treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(treeSet.contains("abc"));
System.out.println(treeSet.isEmpty());
}
}
保存Person类型
需实现Comparable接口
Person.java
package com.aggregation.demo03;
import java.util.Objects;
/**
* 人类
* @author 大白很白
*/
public class Person implements Comparable<Person>{
@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,返回n2,否则返回n1
}
private String name;
private int 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;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// @Override
// public int hashCode() {
// int n1=this.name.hashCode();
// int n2=this.age;
//
// return n1+n2;
// }
//
// @Override
// public boolean equals(Object obj) {
// if (this==obj){
// return true;
// }
// if (obj==null){
// return false;
// }
// if (obj instanceof Person){
// Person p = (Person)obj;
//
// if (this.name.equals(p.getName())&&this.age==p.getAge()){
// return true;
// }
// }
// return false;
// }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
return getAge() == person.getAge() && Objects.equals(getName(), person.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
}
Demo05.java
package com.aggregation.demo03;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 使用TreeSet保存数据
* 存储结构:红黑树
* 要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
* @author 大白很白
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> persons = new TreeSet<>();
//1添加元素
Person p1 = new Person("xyz",18);
Person p2 = new Person("hello",19);
Person p3 = new Person("zz",20);
Person p4 = new Person("zz",21);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
//元素个数:4
//[Person{name='hello', age=19}, Person{name='xyz', age=18}, Person{name='zz', age=20}, Person{name='zz', age=21}]
//2删除
//persons.remove(p1);
//persons.remove(new Person("xyz",18));
//System.out.println("删除之后:"+persons.size());
//3遍历
//3.1使用增强for
for (Person person:persons) {
System.out.println(person);
}
//3.2使用迭代器
System.out.println("------------------------");
Iterator<Person> it = persons.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4判断
System.out.println(persons.contains(p1));
System.out.println(persons.isEmpty());
}
}
Comparator接口
Comparator:实现定制比较(比较器)
Demo06.java
package com.aggregation.demo03;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet集合的使用
* Comparator:实现定制比较(比较器)
* Comparable:可比较的
* @author 大白很白
*/
public class Demo06 {
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;
}
});
Person p1 = new Person("xyz",18);
Person p2 = new Person("hello",19);
Person p3 = new Person("zz",20);
Person p4 = new Person("dd",20);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println(persons.toString());
}
}
TreeSet案例
要求:使用TreeSet集合实现字符串按照长度进行排序
Demo07.java
package com.aggregation.demo03;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 要求:使用TreeSet集合实现字符串按照长度进行排序
* helloworld zhang lisi wangwwu beijing xian nanjing
* Comparator接口实现定制比较
*/
public class Demo07 {
public static void main(String[] args) {
//创建集合,并指定比较规则
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("helloworld");
treeSet.add("cat");
treeSet.add("superman");
treeSet.add("puppy");
treeSet.add("lightning");
treeSet.add("ball");
System.out.println(treeSet.toString());
}
}
Map集合
map接口的特点:
- 用于存储任意键值对(Key-Value)
- 键:无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
Map父接口
- 特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复
- 方法:
- V put(K key,V value) //将对象存入到集合中,关联键值。key重复则覆盖原值。
- Object get(Object key) //根据键获取对应的值。
- Set
//返回所有Key。 - Collection
values() //返回包含所有值的Collection集合。 - Set<Map.Entry<K,V>> //键值匹配的Set集合。
Map接口的使用
Demo01.java
package com.aggregation.demo04;
import java.util.HashMap;
import java.util.Map;
/**
* Map接口的使用
* 特点:(1)存储键值对(2)键不能重复,值可以重复(3)无序
* @author 大白很白
*/
public class Demo01 {
public static void main(String[] args) {
//创建Map集合
Map<String, String> map = new HashMap<>();
//1添加元素
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
map.put("cn","zhongguo");//元素并未增加,但值会覆盖
System.out.println("元素个数:"+map.size());
System.out.println(map.toString());
//2删除
// map.remove("usa");
// System.out.println("删除之后:"+map.size());
//3遍历
//3.1使用keySet();
System.out.println("---------------keySet()-------------------");
//Set<String> keySet = map.keySet();
for (String key :map.keySet()) {
System.out.println(key+"----"+map.get(key));
/*---------------keySet()-------------------
usa----美国
uk----英国
cn----zhongguo*/
}
//3.2使用entrySet()方法
System.out.println("-----------entrySet()--------------");
//Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Map.Entry<String, String> entry:map.entrySet()) {
System.out.println(entry.getKey()+"--------"+entry.getValue());
/* -----------entrySet()--------------
usa--------美国
uk--------英国
cn--------zhongguo*/
}
//4判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("泰国"));
}
}
Map集合的实现类
- HashMap【重点】:
- JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value。
- Hashtable:
- JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。
- Properties:
- Hashtable的子类,要求key和value都是String。通常用于配置文件的读取。
- TreeMap:
- 实现了SortedMap接口(是Map的子接口),可以对key自动排序。
HashMap的使用
Students.java
package com.aggregation.demo04;
import java.util.Objects;
public class Student {
private String name;
private int stuNo;
public Student() {
}
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;
}
public Student(String name, int stuNo) {
this.name = name;
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 instanceof Student)) return false;
Student student = (Student) o;
return getStuNo() == student.getStuNo() && Objects.equals(getName(), student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getStuNo());
}
}
Demo02.java
package com.aggregation.demo04;
import java.util.HashMap;
import java.util.Map;
/**
* HashMap集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 使用key得hashcode和equals作为重复依据
* author 大白很白
*/
public class Demo02 {
public static void main(String[] args){
//刚创建hashmap之后没有添加元素table==null size=0 目的:节省空间
//创建集合
HashMap<Student, String> students = new HashMap<>();
//1添加元素
Student s1 = new Student("小红",1);
Student s2 = new Student("小绿",2);
Student s3 = new Student("小黑",3);
students.put(s1,"地球");
students.put(s2,"火星");
students.put(s3,"水星");
//students.put(s3,"金星");
students.put(new Student("小红",1),"黑洞");
System.out.println("元素个数:"+students.size());
System.out.println(students.toString());
//2删除
// students.remove(s1);
// System.out.println("删除之后:"+students.size());
// System.out.println(students.toString());
//3遍历
//3.1使用keySet();
System.out.println("------------keySet()------------------");
for (Student key:students.keySet()) {
System.out.println(key.toString()+"---------"+students.get(key));
}
//3.2使用entrySet();
System.out.println("-------------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.containsValue("宇宙"));
}
}
HashMap源码分析
1 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //hashMap初始容量大小
2 static final int MAXIMUM_CAPACITY = 1 << 30;//hashMap的数组最大容量
3 static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
4 static final int TREEIFY_THRESHOLD = 8;//jdk1.8当链表长度大于8时,调整成红黑树
5 static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8 当链表长度小于6时,调整成链表
6 static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树
7 transient Node<K,V>[] table;//哈希表中的数组
8 size;//元素个数
无参构造
public HashMap(){
this.loadFactor = DEFAULT_LOAD_FACTOR;// all other fields defaulted
}
put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
总结:
- HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数。
- jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
- jdk1.8当链表长度小于6时,调整成链表
- jdk1.8以前,链表是头插入,jdk1.8以后是尾插入
TreeMap的使用
需实现Comparable接口,或者使用定制比较comparator
Student.java
package com.aggregation.demo04;
import java.util.Objects;
public class Student implements Comparable<Student>{
@Override
public int compareTo(Student o) {
//int n1=this.name.compareTo(o.getName());
int n2=this.stuNo-o.getStuNo();
return n2;
}
private String name;
private int stuNo;
public Student() {
}
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;
}
public Student(String name, int stuNo) {
this.name = name;
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 instanceof Student)) return false;
Student student = (Student) o;
return getStuNo() == student.getStuNo() && Objects.equals(getName(), student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getStuNo());
}
}
Demo03.java
package com.aggregation.demo04;
import java.util.Map;
import java.util.TreeMap;
/**
* TreeMap的使用
* 存储结构:红黑树
* author 大白很白
*/
public class Demo03 {
public static void main(String[] args) {
//新建集合 或用定制比较 comparator
TreeMap<Student, String> treeMap = new TreeMap<>();
//1添加元素
Student s1 = new Student("小红",1);
Student s2 = new Student("小绿",2);
Student s3 = new Student("小黑",3);
treeMap.put(s1,"成都");
treeMap.put(s2,"广州");
treeMap.put(s3,"上海");
treeMap.put(new Student("小黑",3),"北京");//值覆盖
System.out.println("元素个数:"+treeMap.size());
System.out.println(treeMap.toString());
//2删除
//treeMap.remove(s3);
//treeMap.remove(new Student("小红",1));
//System.out.println("删除之后:"+treeMap.size());
//3遍历
//3.1使用keySet()
System.out.println("-----------使用keySet()---------");
for (Student key:treeMap.keySet()) {
System.out.println(key+"-----"+treeMap.get(key));
}
//3.2使用entrySet()
System.out.println("-------------使用entrySet()-----------");
for (Map.Entry<Student, String>entry:treeMap.entrySet()) {
System.out.println(entry.getKey()+"-----"+entry.getValue());
}
//判断
System.out.println(treeMap.containsKey(new Student("小黑",3)));
}
}
Collections工具类
-
概念:集合工具类,定义了除了存取以外的集合常用方法。
-
方法:
-
public static void reverse(List<?> list) //反转集合中元素的顺序
-
public static void shuffle(List<?> list) //随机重置集合元素的顺序
-
public static void sort(List
list) //升序排序(元素类型必须实现Comparable接口)
-
Demo04.java
package com.aggregation.demo04;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 演示Collections工具类的使用
* @author 大白很白
*/
public class Demo04 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(15);
list.add(17);
list.add(2);
list.add(8);
list.add(10);
//sort排序
System.out.println("排序之前:"+list.toString());
Collections.sort(list);
System.out.println("排序之后:"+list.toString());
// 排序之前:[20, 15, 17, 2, 8, 10]
// 排序之后:[2, 8, 10, 15, 17, 20]
//binarySearch二分查找
int i = Collections.binarySearch(list, 15);
System.out.println(i);//3,找到>=0;没找到,负数
//copy复制
List<Integer> dest = new ArrayList<>();//长度不同,需注意
for (int j = 0; j < list.size(); j++) {
dest.add(0);
}
Collections.copy(dest,list);
System.out.println(dest.toString());//[2, 8, 10, 15, 17, 20]
//reverse反转
Collections.reverse(list);
System.out.println("反转之后:"+list);//反转之后:[20, 17, 15, 10, 8, 2]
//shuffle 打乱
Collections.shuffle(list);
System.out.println("打乱之后:"+list);//打乱之后:[8, 2, 10, 17, 15, 20]
//补充: list转成数组
System.out.println("--------list转成数组-----------");
Integer[] arr = list.toArray(new Integer[7]);
System.out.println(arr.length);//7
System.out.println(Arrays.toString(arr));//[15, 20, 8, 2, 17, 10, null]
//数组转成集合
System.out.println("----------数组转成集合---------");
String[] names={"张三","李四","王武"};
//集合是一个受限集合,不能添加和删除
List<String> list2 = Arrays.asList(names);
//list2.add("赵六");
//list2.remove(0);
System.out.println(list2);
//把基本类型数组转成集合时,需要修改为包装类
Integer[] nums = {100,200,300,400,500};
List<Integer> list3 = Arrays.asList(nums);
System.out.println(list3);//[100, 200, 300, 400, 500]
}
}
集合总结
- 集合的概念:
- 对象的容器,和数组类似,定义了多个对象进行操作的常用方法。
- List集合:
- 有序、有下标、元素可以重复。(ArrayList、LinkedList、Vector)
- Set集合
- 无序、无下标、元素不可重复。(HashSet、TreeSet)
- Map集合:
- 存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable、TreeMap)
- Collections:
- 集合工具类,定义了除了存取以外的集合常用方法。