一、集合的概念
什么是集合
-
概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
-
和数组的区别:
- 数组长度固定,集合长度不固定。
- 数组可以存储基本类型和引用类型,集合只能存储引用类型.
-
位置:
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 collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
Collection接口的使用
1.添加元素
2.删除元素
3.遍历元素
4.判断
*/
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.删除元素
/*System.out.println("================================");
collection.remove("榴莲");
collection.clear();
System.out.println("删除之后:"+collection.size());*/
//3.遍历元素(重点)
System.out.println("=================================");
//3.1.使用增强for循环
for (Object o : collection) {
System.out.println(o);
}
//3.2.使用迭代器(迭代器专门用来遍历集合的一种方式)
//hasNext();有没有下一个元素
//next();获取下一个元素
//remove();删除当前元素
System.out.println("==================================");
Iterator it = collection.iterator();
while (it.hasNext()){
String s = (String)it.next();
System.out.println(s);
//不能使用collection删除方法
//collection.remove(s);//并发修改异常
it.remove();
}
System.out.println("元素个数:"+collection.size());
//4.判断
System.out.println("==================================");
System.out.println(collection.contains("西瓜"));
System.out.println(collection.isEmpty());
}
}
package collection;
//学生类
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 +
'}';
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
//Collection的使用:保存学生信息
public class Demo02 {
public static void main(String[] args) {
//新建Collection对象
Collection collection = new ArrayList();
Student s1 = new Student("卡萨丁",20);
Student s2 = new Student("杰斯",20);
Student s3 = new Student("亚索",20);
//1.添加数据
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println("元素个数:"+collection.size());
System.out.println(collection.toString());
//2.删除
/*collection.remove(s1);
System.out.println("==================================");
collection.remove(new Student("卡萨丁",20));
collection.clear();//只是删除了地址,并没有删除对象
System.out.println("删除之后:"+collection.size());*/
//3.遍历
//3.1 增强for
System.out.println("==================================");
for (Object o : collection) {
Student s = (Student)o;
System.out.println(s.toString());
}
//3.2 迭代器:hasNext(); next(); remove(); 迭代过程中不能使用collection的删除方法
System.out.println("==================================");
Iterator it = collection.iterator();
while (it.hasNext()){
Student s = (Student)it.next();
System.out.println(s.toString());
}
//4.判断
System.out.println("==================================");
System.out.println(collection.contains(s1));
System.out.println(collection.isEmpty());
}
}
三、List接口与实现类
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) //返回from Index和toIndex之间的集合元素。
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
//List接口的使用
//特点:1.有序、有下标 2.可以重复
public class Demo03 {
public static void main(String[] args) {
//先创建集合对象
List list = new ArrayList<>();
//1.添加元素
list.add("苹果");
list.add("小米");
list.add("华为");
System.out.println("元素个数:"+list.size());
System.out.println(list.toString());
//2.删除元素
/*list.remove("华为");
list.remove(0);
System.out.println("删除之后:"+list.size());
System.out.println(list.toString());*/
//3.遍历
//3.1使用for遍历
System.out.println("====================================");
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
//3.2使用增强for
System.out.println("====================================");
for (Object o : list) {
System.out.println(o);
}
//3.3使用迭代器
System.out.println("====================================");
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//3.4使用列表迭代器,和Itertor的区别:ListIterator可以向前或向后遍历、添加、删除、修改元素
System.out.println("====================================");
ListIterator lit = list.listIterator();
while (lit.hasNext()){
System.out.println(lit.next());
}
//此时指针已经到了最后一个元素。
System.out.println("====================================");
while (lit.hasPrevious()){
System.out.println(lit.previousIndex()+":"+lit.previous());
}
//4.判断
System.out.println("====================================");
System.out.println(list.contains("小米"));
System.out.println(list.isEmpty());
//5.获取位置
System.out.println("====================================");
System.out.println(list.indexOf("小米"));
}
}
package collection;
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());
System.out.println(list.toString());
//2.删除操作
/*list.remove(0);
//list.remove((Object)20);
//list.remove(new Integer(20));
System.out.println("删除之后:"+list.size());
System.out.println(list.toString());*/
//3.补充方法subList
List list1 = list.subList(1,3);//返回子集合,含头不含尾.
System.out.println(list1.toString());
}
}
List实现类
-
ArrayList(重点):
- 数组结构实现,查询快、增删慢;
- JDK1.2 版本支持,运行效率快、线程不安全。
-
Vector:
- 数组结构实现,查询快、增删慢;
- JDK1.0 版本支持,运行效率慢、线程安全。
-
LinkedList:
- 链表结构实现,查询慢、增删快;
- JDK1.2 版本支持,运行效率快、线程不安全。
ArrayList的使用
package collection;
//学生类
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.判断obj是否null
if (obj==null){
return false;
}
//3.判断是否是同一个类型
// if (this.getClass()==obj.getClass()){}
//intanceof 判断对象是否是某种类型
if (obj instanceof Student){
//4.强制转换类型
Student s=(Student)obj;
//5.比较属性
if (this.name.equals(s.getName())&&this.age==s.getAge()){ //字符串的比较用equals
return true;
}
}
//不满足条件返回false
return false;
}
}
package collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
//ArrayList的使用
//储存结构;数组,查找遍历速度快,增删慢
public class Demo05 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList<>();
//1.添加元素
Student s1 = new Student("食发鬼",20);
Student s2 = new Student("圣迭戈",22);
Student s3 = new Student("郭德纲",24);
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));//里面有equals(this==obj)这个方法
System.out.println("删除之后:"+arrayList.size());*/
//3.遍历元素(重点)
//3.1使用迭代器
System.out.println("======================================");
Iterator it = arrayList.iterator();
while(it.hasNext()){
Student s = (Student)it.next();
System.out.println(s.toString());
}
//3.2列表迭代器
System.out.println("======================================");
ListIterator lit = arrayList.listIterator();
while(lit.hasNext()){
Student s = (Student)lit.next();
System.out.println(s.toString());
}
System.out.println("======================================");
while(lit.hasPrevious()){
Student s = (Student)lit.previous();
System.out.println(s.toString());
}
//4.判断
System.out.println(arrayList.contains(new Student("圣迭戈",22)));
System.out.println(arrayList.isEmpty());
//5.查找
System.out.println(arrayList.indexOf(new Student("圣迭戈",22)));
}
}
ArrayList源码分析
-
DEFAULT_CAPACITY=10
;默认容量。- 注意:如果没有向集合中添加任何元素时,容量0;添加一个元素之后,容量为10;每次扩容大写是原来的1.5倍。
-
elementData 存放元素的数组。
-
size 实际元素的个数。
-
add() 添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(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 collection;
import java.util.Enumeration;
import java.util.Vector;
//演示Vector集合的使用
//存储结构:数组
public class Demo06 {
public static void main(String[] args) {
//创建集合
Vector vector = new Vector<>();
//1.添加元素
vector.add("草莓");
vector.add("芒果");
vector.add("西瓜");
System.out.println("元素个数:"+vector.size());
System.out.println(vector.toString());
//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 collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
//ListedList的使用
//存储结构:双向链表
public class Demo07 {
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.删除
/*System.out.println("=======================================");
linkedList.remove(new Student("刘德华",20));
System.out.println("删除之后:"+linkedList.size());
linkedList.clear();
System.out.println("删除之后:"+linkedList.size());*/
//3.遍历
//3.1for遍历
System.out.println("=======================================");
for (int i = 0; i <linkedList.size() ; i++) {
System.out.println(linkedList.get(i));
}
//3.2增强for
System.out.println("=======================================");
for (Object o : linkedList) {
Student s = (Student)o;
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());
}
//3.4使用列表迭代器
System.out.println("=======================================");
ListIterator lit = linkedList.listIterator();
while (lit.hasNext()){
Student s = (Student)lit.next();
System.out.println(s.toString());
}
//4.判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
//5.获取
System.out.println(linkedList.indexOf(s3));
}
}
LinkedList源码分析
- int size: 集合的大小
- 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的区别
四、泛型和工具类
- Java 泛型是JDK1.5中引入的一个新特性,本质是参数化类型,把类型作为参数传递。
- 常见形式有泛型类、泛型接口、泛型方法。
- 语法:<T,….> T称为类型占位符,表示一种引用类型。
- 好处:
- 提高代码的重用性;
- 防止类型转换异常,提高代码的安全性。
泛型类
package generic;
//泛型类
//语法:类名<T>
//T是类型占位符,表示引用类型,如果编写多个使用逗号隔开
public class MyGeneric<T> {
//使用泛型T
//1.创建变量
T t;
//2.泛型作为方法的参数
public void show(T t){
//T t1 = new T();//不能new对象,因为T不确定。
System.out.println(t);
}
//3.泛型作为方法的返回值
public T getT(){
return t;
}
}
泛型接口
package generic;
//泛型接口
//语法:接口名<T>
//注意:不能泛型静态常量
public interface MyInterface<T> {
String name = "张三";
T server(T t);
}
package generic;
public class MyInterfaceImpl implements MyInterface<String > {
@Override
public String server(String t) {
System.out.println(t);
return t;
}
}
package generic;
public class MyInterfaceImpl2<T> implements MyInterface<T>{
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
泛型方法
package generic;
//泛型方法
//语法:<T> 返回值类型
public class MyGenericMethod{
//泛型方法
public <T> T show(T t){
System.out.println("泛型方法:"+t);
return t;
}
}
package generic;
public class TextGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//注意:1.泛型只能使用引用类型。2.不同泛型之间不能相互赋值
MyGeneric<String> myGeneric = new MyGeneric<>();
myGeneric.t= "hello";
myGeneric.show("大家好,加油");
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric1 = new MyGeneric<Integer>();
myGeneric1.t = 100;
myGeneric1.show(200);
Integer integer = myGeneric1.getT();
//泛型接口
System.out.println("===================================");
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.server("xxxxxxx");
MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<Integer>();
impl2.server(1000);
//泛型方法
System.out.println("===================================");
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("中国加油");//这里输入什么就是什么类型
myGenericMethod.show(200);
myGenericMethod.show(3.14);
}
}
泛型集合
-
概念
- 参数化类型、类型安全的集合,强制集合元素的类型必须一致。
-
特点
- 编译时即可检查,而非运行时抛出异常。
- 访问,不必类型转换(拆箱)。
- 不同泛型之间引用不能相互赋值,泛型不存在多态。
package generic;
import collection.Student;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("xxx");
arrayList.add("yyy");
//arrayList.add(10);//有<String>约束这个就添加不了了。
//arrayList.add(20);
for (String s : arrayList) {
System.out.println(s);
}
ArrayList<Student> arrayList1 = new ArrayList<Student>();
Student s1 = new Student("刘德华",20);
Student s2 = new Student("郭富城",22);
Student s3 = new Student("梁朝伟",18);
arrayList1.add(s1);
arrayList1.add(s2);
arrayList1.add(s3);
Iterator<Student> it = arrayList1.iterator();
while(it.hasNext()){
Student student= it.next();
System.out.println(student.toString());
}
}
}
五、Set接口与实现类
Set子接口
- 特点:无序、无下标、元素不可重复。
- 方法:全部继承自Collection中的方法。
package collection2;
import java.util.HashSet;
import java.util.Iterator;
//测试Set接口的使用
//特点:1.无序、没有下标。2.不能重复
public class Demo01 {
public static void main(String[] args) {
//创建集合
HashSet 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 ,不能使用for循环,因为它无序没有下标
System.out.println("======================================");
for (Object o : set) {
System.out.println(o);
}
//3.2使用迭代器
System.out.println("======================================");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//4.判断
System.out.println(set.contains("华为"));
System.out.println(set.isEmpty());
}
}
Set实现类
-
HashSet(重点):
- 基于HashCode实现元素不重复。
- 当存入元素的HashCode相同时,会调用equals进行判断,如果为true,则拒绝后者写入。
-
TreeSet:
- 基于排列顺序实现元素不重复。
- 实现了SortedSet接口,对集合元素自动排序。
- 元素对象的类型必须实现Comparable接口,指定排序规则。
- 通过CompareTo方法确定是否为重复元素。
HashSet的使用
package collection2;
import java.util.HashSet;
import java.util.Iterator;
//HashSet集合的使用
//存储结构:哈希表(数组+链表+红黑树)
public class Demo02 {
public static void main(String[] args) {
//新建集合
HashSet<String> hashSet = new HashSet<String>();
//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.size());*/
//3.遍历操作
//3.1 增强for
System.out.println("==================================");
for (String s : hashSet) {
System.out.println(s);
}
//3.2 使用迭代器
System.out.println("==================================");
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//4.判断
System.out.println("==================================");
System.out.println(hashSet.contains("傅里叶"));
System.out.println(hashSet.isEmpty());
}
}
package collection2;
import java.util.HashSet;
import java.util.Iterator;
//HashSet集合的使用
//存储结构:哈希表(数组+链表+红黑树)
//存储过程(重复依据)
//1.根据hascode计算保存的位置,如果此位置为空,则直接保存、如果不为空执行第二部
//2.在执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet<Person> person = new HashSet<>();
//1.添加元素
Person p1 = new Person("哈士奇",20);
Person p2 = new Person("萨摩耶",30);
Person p3 = new Person("阿拉斯加",30);
person.add(p1);
person.add(p2);
person.add(p3);
//person.add(p3);//不能重复
person.add(new Person("哈士奇",20));
System.out.println("元素个数:"+person.size());
System.out.println(person.toString());
//删除操作
/*person.remove(p3);
person.remove(new Person("哈士奇",20));
System.out.println("删除之后:"+person.size());
System.out.println("删除之后:"+person.toString());*/
//3遍历(重点)
//3.1 使用增强for
System.out.println("==============================");
for (Person person1 : person) {
System.out.println(person1.toString());
}
//3.2 迭代器
System.out.println("==============================");
Iterator iterator = person.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//4.判断
System.out.println("==============================");
System.out.println(person.contains(new Person("哈士奇",20)));
System.out.println(person.isEmpty());
}
}
- HashSet存储方式
package collection2;
import java.util.Objects;
//人类
public class Person implements Comparable<Person>{
private String name;
private int age;
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 || 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);
//补充:里面用到了一个数:31
//1.31是一个质数,减少数列冲突
//2.31是提高执行效率 31*i=(i<<5)-i
}
/*@Override
public int hashCode() {
int n1 = this.name.hashCode();
int n2 = this.age;
return n1+n2;
}
@Override
public boolean equals(Object obj) {
//1.判断两个对象是否是同一个引用
if (this == obj) {
return true;
}
//2.判断obj是否null
if (obj == null) {
return false;
}
//3.判断是否是同一个类型
// if (this.getClass()==obj.getClass()){}
//intanceof 判断对象是否是某种类型
if (obj instanceof Person) {
//4.强制转换类型
Person s = (Person) obj;
//5.比较属性
if (this.name.equals(s.getName()) && this.age == s.getAge()) { //字符串的比较用equals
return true;
}
}
//不满足条件返回false
return false;
}*/
//先按姓名比,再按年龄比
@Override
public int compareTo(Person o) {
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age-o.getAge();
return n1==0?n2:n1;
}
}
TreeSet的使用
package collection2;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用
* 存储结构:红黑树
*/
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("hello");
System.out.println("元素个数:"+treeSet.size());
System.out.println(treeSet.toString());
//2.删除
/*treeSet.remove("xyz");
System.out.println("删除之后:"+treeSet.size());*/
//3.遍历
//3.1 使用增强for
System.out.println("===========================");
for (String s : treeSet) {
System.out.println(s);
}
//3.2使用迭代器
System.out.println("===========================");
Iterator<String > it = treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//4.判断
System.out.println("===========================");
System.out.println(treeSet.contains("abc"));
}
}
package collection2;
import java.util.Iterator;
import java.util.TreeSet;
/**
* 使用TreeSet保存数据
* 存储结构:红黑树
* 要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> persons = new TreeSet<>();
//1.添加元素
Person p2 = new Person("萨摩耶",30);
Person p3 = new Person("阿拉斯加",40);
Person p4 = new Person("阿拉斯加",30);
Person p1 = new Person("哈士奇",20);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
//2.删除
/*persons.remove(p1);
System.out.println(persons.size());*/
//3.遍历
//3.1使用增强for
System.out.println("==========================");
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("==========================");
System.out.println(persons.contains(new Person("萨摩耶",30)));
}
}
- Comparator接口
package collection2;
import sun.reflect.generics.tree.Tree;
import java.util.Comparator;
import java.util.TreeSet;
/**
* TreeSet集合的使用
* Comparator:实现定制比较(比较器)
* Comparable:可比较的
*/
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 p2 = new Person("xyz",30);
Person p3 = new Person("helli",40);
Person p4 = new Person("zhangsan",30);
Person p1 = new Person("lisi",30);
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println(persons.toString());
}
}
- TreeSet案例
package collection2;
import java.util.Comparator;
import java.util.TreeSet;
/**
* 要求:使用TreeSet集合实现字符串按照长度进行排序
* 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("pingguo");
treeSet.add("lisi");
treeSet.add("zhangsan");
treeSet.add("cat");
treeSet.add("nanjing");
treeSet.add("xian");
System.out.println(treeSet.toString());
}
}
六、 Map接口与实现类
Map集合
Map父接口
-
特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复。
-
方法:
V put(K key, V value)
//将对象存到集合中,关联键值.key重复则覆盖原值。Object get(Object key)
//根据键获得对应的值.Set<K>
//返回所有Key.Collection<V> values()
//返回包含所有值的Collection集合.Set<Map.Entry<K, V>>
// 键值匹配的Set集合.
package map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
Map接口的使用
特点:1.存储键值对 2.键不能重复,值可以重复 3.无序
*/
public class Demo01 {
public static void main(String[] args) {
//创建Map集合
HashMap<String, String > map = new HashMap<>();
//1.添加元素
map.put("cn","中国");
map.put("uk","英国");
map.put("usa","美国");
map.put("cn","zhongguo");//不会添加新的key,但是被新的value给替换掉了。
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("========================================");
Set<String > keyset = map.keySet();
for (String key : keyset) {
System.out.println(key+"---"+map.get(key));
}
//3.2使用entrySet()方法
System.out.println("========================================");
Set<Map.Entry<String,String >> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
//4.判断
System.out.println("========================================");
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自动排序,Key需实现Comparable接口。
HashMap的使用
package map;
import java.util.Objects;
public class Student implements Comparable<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);
}
@Override
//这里比的是学号
public int compareTo(Student o) {
int n1 = this.stuNo-o.getStuNo();
return n1;
}
}
package map;
import java.util.HashMap;
import java.util.Map;
/*
HashMap集合的使用
存储结构:哈希表(数组+链表+红黑树)
使用Key可hashcode和equals作为重复
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
HashMap<Student, String > students = new HashMap<Student, String >();
//刚创建hashmap之后没有添加元素 table=null,size=0. 目的是节省空间。
//添加元素
Student s1 = new Student("孙悟空",100);
Student s2 = new Student("猪八戒",101);
Student s3 = new Student("沙和尚",102);
students.put(s1,"北京");
students.put(s2,"上海");
//students.put(s2,"北京");
students.put(s3,"杭州");
//students.put(s3,"南京");
students.put(new Student("沙和尚",102),"杭州");//需要重写equals和hashcode方法才添加不进去,否则他们添加的地址不同,可以添加。
System.out.println("元素个数:"+students.size());
System.out.println(students.toString());
//2.删除
/*students.remove(s1);
System.out.println("删除之后:"+students.size());*/
//3.遍历
//3.1 使用keySet();
System.out.println("====================================================");
for (Student key : students.keySet()) {
System.out.println(key.toString()+"---"+students.get(key));
}
//3.2使用entrySet();
System.out.println("====================================================");
for (Map.Entry<Student, String> entry : students.entrySet()) {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
//4.判断
System.out.println("====================================================");
System.out.println(students.containsKey(new Student("孙悟空",100)));
System.out.println(students.containsValue("杭州"));
}
}
HashMap源码分析
1.static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // hasMap初始容量大小
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;//元素个数
总结:
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以后是尾插入。
HashSet源码分析:HashSet的存储结构就是HashMap,它的add方法调用的就是map的put方法,把元素作为map的key传进去的。
TreeMap的使用
package map;
import java.util.Map;
import java.util.TreeMap;
/*
TreeMap的使用
存储结构:红黑树
和TreeSet区别:TreeSet用的是map的key值。
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合(也可以定制比较)
TreeMap<Student, String > treemap = new TreeMap<Student, String>();
//1.添加元素
Student s1 = new Student("孙悟空",100);
Student s2 = new Student("猪八戒",101);
Student s3 = new Student("沙和尚",102);
treemap.put(s1,"北京");
treemap.put(s2,"上海");
treemap.put(s3,"深圳");
treemap.put(new Student("沙和尚",102),"南京");//这里比的是学号,加不进去,但value值可以替换
System.out.println("元素个数:"+treemap.size());
//这里必须重写compareTo方法,否则会异常
System.out.println(treemap.toString());
//2.删除
/*treemap.remove(new Student("猪八戒",101),"上海");
System.out.println(treemap.size());*/
//3.遍历
//3.1使用keySet();
System.out.println("======================================");
for (Student key : treemap.keySet()) {
System.out.println(key+"---"+treemap.get(key));
}
//3.2 使用entrySet();
System.out.println("======================================");
for (Map.Entry<Student, String> entry : treemap.entrySet()) {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
//4.判断
System.out.println("======================================");
System.out.println(treemap.containsKey(new Student("沙和尚",102)));
}
}
七、Collections工具类
- 概念:集合工具类,定义了除了存取以外的集合常用方法。
- 方法:
public static void reverse(List<?> list)
//反转集合中元素的顺序.public static void shuffle(List<?> list)
//随机重置集合元素的顺序.public static void sort(List<T> list)
//升序排序(元素类型必须实现Comparable接口).
package map;
import java.util.*;
/*
演示Collections工具类的使用
*/
public class Demo04 {
public static void main(String[] args) {
ArrayList<Integer> 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,13);//有的话输出位置,没有的话输出负数。
System.out.println(i);
//copy复制
ArrayList<Integer> dest = new ArrayList<>();
//要保证两个数组的长度一样,否则会异常。比如用一个for循环
for (int k = 0; k <list.size() ; k++) {
dest.add(0);
}
Collections.copy(dest,list);
System.out.println(dest.toString());
//reverse反转
Collections.reverse(list);
System.out.println("反转之后:"+list);
//shuffle打乱
Collections.shuffle(list);
System.out.println("打乱之后:"+list);
//补充:list转成数组
System.out.println("===============================================");
Integer[] arr = list.toArray(new Integer[0]);//这个数比长度打的话会多余部分显示null.
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//数组转成集合
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);
}
}
八、总结
-
集合的概念:
- 对象的容器,存储对象的对象,定义了对多个对象进行操作的常用方法。
-
List集合:
- 有下标、元素可以重复。(ArrayList、LinkedList、Vector)。
-
Set集合:
- 无下标、元素不可重复。(HashSet、LinkedHashSet、TreeSet).
-
Map集合:
- 存储一对数据,键不可重复,值可里复。(HasnMap、HashTable、Properties、TreeMap)。
-
Collections:
- 集合工具类,定义了除了存取以外的集合常用方法。