文章目录
集合
简介
存储多个元素的容器,定义了对多个对象进行操作的常用方法,可以实现数组的功能。
与数组的区别
- 元素类型
集合:只能是引用类型(存储基本类型时自动装箱)
数组:基本类型,引用类型
- 元素个数
集合:个数不固定,可以任意扩容
数组:固定,不能改变容量
Java的集合体系
单列集合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7tSqbY7i-1630411322597)(D:\markdown图片\捕获1.PNG)]
双列集合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ulNwsxv-1630411322606)(D:\markdown图片\捕获2.PNG)]
Collection接口
实例一
package com.collection.one;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTestFirst {
public static void main(String[] args) {
//collection接口的基本使用一
//创建对象
Collection collection = new ArrayList();//ArrayList是有序的
//1.添加元素
collection.add("苹果");
collection.add("橘子");
collection.add("山竹");
System.out.println("集合的元素个数:"+collection.size());
System.out.println(collection);
//2.遍历元素
//2.1通过增强for循环来遍历
System.out.println("-----通过增强for循环来遍历-----");
for (Object o : collection) {
System.out.println(o);
}
//2.2通过迭代器来遍历
System.out.println("-----通过迭代器来遍历-----");
Iterator it = collection.iterator();
while (it.hasNext()) {
//Object o = it.next();
String s = (String)it.next(); //当前集合中存储的是字符串类型,所以可以强制类型转换成字符串类型
System.out.println(s);
//这里不能使用collection中的remove()方法进行删除元素,只能用迭代器提供的remove()方法进行删除
//it.remove();
}
//System.out.println("元素个数:"+collection.size());
//3.判断
//判断集合中是否包含“榴莲”
System.out.println(collection.contains("榴莲"));
//判断集合中是否包含“山竹”
System.out.println(collection.contains("山竹"));
//判断集合是否是空
System.out.println(collection.isEmpty());
//4.删除元素
//删除指定元素
collection.remove("苹果");
System.out.println(collection);
//清空集合
collection.clear();
System.out.println("元素个数:"+collection.size());
}
}
实例二
//首先建立一个Student类
package com.collection.one;
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 com.collection.one;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTestSecond {
public static void main(String[] args) {
Student s1 = new Student("张三",18);
Student s2 = new Student("李四",20);
Student s3 = new Student("王二",19);
//创建集合
Collection collection = new ArrayList();
//1.添加元素
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println("元素个数:"+collection.size());
System.out.println(collection.toString());//不加toString()也可以
//2.遍历元素
//2.1通过增强for遍历元素
System.out.println("-----增强for进行遍历-----");
for (Object o : collection) {
Student s = (Student) o;
System.out.println(s);
}
//2.2通过迭代器进行遍历
System.out.println("-----迭代器进行遍历-----");
Iterator it = collection.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s);
//此处不能调用collection的任何方法,例如collection的remove()方法,否则会产生并发修改异常
}
//3.判断
//判断是否包含s1
System.out.println(collection.contains(s1));
//判断是否包含下列对象
System.out.println(collection.contains(new Student("王柳",20)));
//判断是否为空
System.out.println(collection.isEmpty());
//4.删除元素
collection.remove(s1);
System.out.println("元素个数:"+collection.size());
//清空集合
collection.clear();
System.out.println("元素个数:"+collection.size());
}
}
List接口
特点
有序,有下标,元素可以重复
常用方法
- void add(int index,Object o) 在指定位置添加元素
- boolean addAll(int index,Collection c) 将一个集合中的元素添加到此集合中的index位置
- Object get(int index) 返回指定位置的元素
- List subList(int fromIndex,int toIndex) 返回formIndex和toIndex之间的集合元素(含头不含尾)
实例一
package com.collection.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Demo01 {
public static void main(String[] args) {
//List接口的使用
//创建集合
List list = new ArrayList();
//1.添加元素
list.add("华为");
list.add("小米");
list.add("oppo");
System.out.println("元素个数:"+list.size());
System.out.println(list);
//可以在指定位置处添加元素
list.add(3,"魅族");
System.out.println(list);
//2.遍历元素
//2.1使用for循环,由于List是有下标的,因此可以使用for循环
System.out.println("-----使用for循环-----");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//2.2使用增强for
System.out.println("-----使用增强for-----");
for (Object o : list) {
System.out.println(o);
}
//2.3使用迭代器
System.out.println("-----使用迭代器-----");
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//2.4使用列表迭代器
System.out.println("-----使用列表迭代器-----");
ListIterator lit = list.listIterator();
System.out.println("------使用列表迭代器从前往后遍历-----");
while (lit.hasNext()){
System.out.println(lit.nextIndex()+":"+lit.next());
}
System.out.println("-----使用列表迭代器从后往前遍历-----");
//由于前面已经进行了从前往后,指针指在了列表的最后一个元素,所以下面可以直接进行从后往前
while (lit.hasPrevious()) {
System.out.println(lit.previousIndex()+":"+lit.previous());
}
//3.判断
System.out.println(list.contains("huawei"));
System.out.println(list.contains("华为"));
System.out.println(list.isEmpty());
//4.获取
System.out.println("-----获取0号元素-----");
System.out.println("0号元素:"+list.get(0));
//删除
list.remove("华为");
//删除指定下标的元素
list.remove(1);
System.out.println(list);
list.clear();
System.out.println(list);//空
}
}
实例二
package com.collection.list;
import java.util.ArrayList;
import java.util.List;
public class Demo02 {
public static void main(String[] args) {
//创建集合
List list = new ArrayList();
//添加元素
list.add(10);
list.add(20);
list.add(30);
System.out.println(list);
//删除元素:注意!!!
list.remove(new Integer(20));//或者把20强转成Object类
System.out.println(list);
//补充方法subList(),返回值仍是一个集合
list.add(40);
list.add(34);
System.out.println(list);
List list1 = list.subList(1,3);
System.out.println(list1);//该方法的前后两个索引也是含头不含尾
}
}
增强for
格式
for(数据类型 变量名:数组或集合对象) {
//循环体,变量即元素
}//通常用于不需要下标的循环遍历
迭代器
遍历Collection集合的通用方式
迭代器的常用方法
- next() 返回迭代的下一个元素对象
- hasNext() 如果仍有元素可迭代,则返回true
- remove() 删除当前元素
使用步骤
- 根据集合对象获取其对象的迭代器对象;
- 判断迭代器中是否有元素;
- 如果有就获取元素。
//举例
Iterator it = list.iterator();
while(it.hasNext()){
String s = (String)it.next();
System.out.println(s);
}
列表迭代器
List集合特有的迭代器,是Iterator的子接口
在迭代时,不可以通过集合对象的方法操作集合中的元素,否则会发生ConcurrentModificationException(并发修改异常)。所以,在使用迭代器时,只能用迭代器的方法操作元素,但其方法是有限的。如果想要其他操作如增加、修改时就要使用列表迭代器。
//2.4使用列表迭代器
System.out.println("使用列表迭代器从前往后遍历");
ListIterator lit = arrayList.listIterator();
while (lit.hasNext()){
String s = (String) lit.next();
System.out.println(s);
}
System.out.println("使用列表迭代器从后往前遍历");
while (lit.hasPrevious()){
String s = (String) lit.previous();
System.out.println(s);
}
List接口的实现类
ArrayList类
- 数组结构实现,查询快,增删慢;
- 运行效率快,线程不安全。
Vector类
- 数组结构实现,查询快,增删慢;
- 运行效率慢,线程安全。
LinkedList类
- 链表结构实现,增删快,查询慢
ArrayList
常用方法
- add() 添加元素
- size() 长度
- remove() 删除元素
- clear() 清空
- contains() 是否包含
- isEmpty() 是否为空
- indexOf() 返回下标
如果没有添加元素时,容量为0,添加一个元素后,容量为10,每次扩容大小为原来的1.5倍。(是容量,不能说长度)
实例
package com.collection.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class Demo03 {
//ArrayList的使用
//数组结构实现
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList();
//1.添加元素
arrayList.add("张杰");
arrayList.add("尊龙");
arrayList.add("古天乐");
System.out.println("元素个数:"+arrayList.size());
System.out.println(arrayList.toString());
//2.遍历元素
//2.1for循环
//2.2增强for
//2.3迭代器
System.out.println("-----使用迭代器-----");
Iterator it = arrayList.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
//2.4使用列表迭代器
System.out.println("使用列表迭代器从前往后遍历");
ListIterator lit = arrayList.listIterator();
while (lit.hasNext()){
String s = (String) lit.next();
System.out.println(s);
}
System.out.println("使用列表迭代器从后往前遍历");
while (lit.hasPrevious()){
String s = (String) lit.previous();
System.out.println(s);
}
//3.判断
System.out.println(arrayList.contains("谢娜"));
System.out.println(arrayList.isEmpty());
//查找
System.out.println(arrayList.indexOf("张杰"));
System.out.println(arrayList.get(1));
//5.删除
arrayList.remove(2);
System.out.println("元素个数"+arrayList.size());
}
}
Vector
常用方法
- add() 添加元素
- size() 长度
- remove() 删除元素
- clear() 清空
- contains() 是否包含
- isEmpty() 是否为空
- indexOf() 返回下标
实例
package com.collection.list;
import java.util.Enumeration;
import java.util.Vector;
public class Demo04 {
//Vector的使用
//数组结构实现
public static void main(String[] args) {
//创建集合
Vector vector = new Vector();
//添加元素
vector.add("hello");
vector.add("world");
vector.add("man");
//使用枚举器遍历
Enumeration elements = vector.elements();
while (elements.hasMoreElements()) {
String s = (String) elements.nextElement();
System.out.println(s);
}
}
}
LinkedList
常用方法
- add() 添加元素
- size() 长度
- remove() 删除元素
- clear() 清空
- contains() 是否包含
- isEmpty() 是否为空
- indexOf() 返回下标
实例
package com.collection.list;
import java.util.LinkedList;
public class Demo05 {
//LinkedList类
//双向链表结构实现
public static void main(String[] args) {
//创建集合
LinkedList linkedList = new LinkedList();
//添加元素
linkedList.add("you");
linkedList.add("your");
linkedList.add("yours");
System.out.println("元素个数:"+linkedList.size());
//遍历
//判断
//查询
//删除
//List的实现类方法有异曲同工之处
}
}
泛型
简介
泛指任意类型,对具体类型的使用起到辅助作用,类似于方法的参数,其本质是参数化类型,把类型作为参数传递,常见形式有泛型类、泛型接口、泛型方法。
好处
- 类型安全,避免了类型转换(防止类型转换异常);
- 提高代码的重用性。
泛型类
package com.collection.list.demo;
/**
* 泛型类的使用
* 语法:类名后面+<T>
* T是占位符,表示各种引用类型
*/
public class MyGeneric <T>{
//使用泛型创建变量
T t;//可以创建变量,不能实例化对象
//泛型作为方法的参数
public void show(T t) {
System.out.println(t);
}
//泛型作为方法的返回值
public T getT() {
return t;
}
}
//测试类
package com.collection.list.demo;
public class TestGeneric {
public static void main(String[] args) {
//泛型类的使用
System.out.println("-----泛型类的使用-----");
MyGeneric<String> myGeneric = new MyGeneric<>();
myGeneric.show("hello");
MyGeneric<Integer> myGeneric1 = new MyGeneric<>();
myGeneric1.show(100);
//注意:1.泛型只能使用引用类型;
//2.不同泛型类型对象之间不能相互赋值。
}
}
泛型接口
package com.collection.list.demo;
public interface MyInterface <T>{
//定义一个泛型接口
String name = "alice";
//不能T t;因为接口中只能定义公共静态常量
T server (T t);
}
对于上述接口有两种使用方法
方法一
package com.collection.list.demo;
public class MyInterfaceImpl implements MyInterface<String> {
//泛型接口的第一种使用
//实现类直接确定泛型T的类型
public String server(String s) {
System.out.println(s);
return s;
}
}
//其测试类
package com.collection.list.demo;
public class TestGeneric {
public static void main(String[] args) {
//泛型接口的第一种使用
System.out.println("-----泛型接口的第一种使用-----");
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.server("hello world");
}
}
方法二
package com.collection.list.demo;
public class MyInterfaceImpl2 <T> implements MyInterface<T>{
//泛型接口的第二种使用方法
//实现类不直接指明泛型T的类型
public T server (T t) {
System.out.println(t);
return t;
}
}
//其测试类
package com.collection.list.demo;
public class TestGeneric {
public static void main(String[] args) {
//泛型接口的第二种使用
System.out.println("-----泛型接口的第二种使用-----");
MyInterfaceImpl2<String> impl2 = new MyInterfaceImpl2<>();
impl2.server("java");
MyInterfaceImpl2<Integer> impl3 = new MyInterfaceImpl2<>();
impl3.server(100);
}
}
泛型方法
package com.collection.list.demo;
public class MyGenericMethod {
public <T> T show(T t) {
System.out.println(t);
return t;
}
}
//测试类
package com.collection.list.demo;
public class TestGeneric {
public static void main(String[] args) {
//泛型方法的使用
System.out.println("-----泛型方法的使用-----");
MyGenericMethod method = new MyGenericMethod();
method.show("String");
method.show(100);//泛型类型由方法参数决定
}
}
泛型集合
避免类型转换异常
//例如
ArrayList <String> arrayList = new ArrayList<String>();//第二个String可以省略
Set接口
特点
无序、无下标、不可重复
方法
全部继承Collection接口的方法
实例
package com.collection.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* set接口的使用
* 特点:无序,无下标,不可重复
* 方法:全部继承collection中的方法
*/
public class Demo01 {
public static void main(String[] args) {
//set接口的使用
//创建集合
Set<String> set = new HashSet<>();
//1.添加元素
set.add("苹果");
set.add("华为");
set.add("小米");
//set.add("苹果");//不会被添加进去
System.out.println("元素个数:"+set.size());
System.out.println(set.toString());
//2.遍历元素
//2.1通过增强for遍历
System.out.println("-----通过增强for遍历-----");
for (String s : set) {
System.out.println(s);
}
//2.2通过迭代器遍历
System.out.println("-----通过迭代器遍历-----");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//3.判断
System.out.println(set.contains("小米"));
System.out.println(set.isEmpty());
//4.删除元素
set.remove("小米");
System.out.println("元素个数:"+set.size());
set.clear();
System.out.println("元素个数:"+set.size());
}
}
Set接口的实现类
HashSet类
- 存储结构:哈希表(数组+链表+红黑树);
- 基于HashCode实现元素不重复;
- 当存入元素的哈希码相同时,会调用equals()方法进行确认,如为true则拒绝后者存入。
TreeSet类
- 基于排列顺序实现元素不重复;
- 实现了SortedSet接口,对集合元素自动排序;
- 元素对象的类型必须实现Comparable接口,指定排序规则,否则出现ClassCastException;
- 通过comparaTo()方法确定是否为重复元素(自己创建的类要自己实现上一条的接口,重写comparaTo()方法);
- 存储结构:红黑树
HashSet
存储过程
- 根据HashCode计算要保存的位置,若此位置为空,直接保存,不为空执行第二步;
- 执行equals()方法,如果equals()方法为true,则认为重复,否则,形成链表。
实例一
package com.collection.set;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用一
* 基于HashCode实现元素不重复
* 无序、无下标、元素不重复
* 存储结构:哈希表(数组+链表+红黑树)
*/
public class Demo02 {
public static void main(String[] args) {
//创建集合
HashSet<String> hashSet = new HashSet<>();
//1.添加元素
hashSet.add("张杰");
hashSet.add("尊龙");
hashSet.add("古天乐");
System.out.println("元素个数:"+hashSet.size());
System.out.println(hashSet);
//2.遍历元素
//2.1增强for
System.out.println("-----增强for遍历-----");
for (String s : hashSet) {
System.out.println(s);
}
//2.2迭代器
System.out.println("-----迭代器-----");
Iterator<String> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//3.判断
System.out.println(hashSet.contains("张杰"));
System.out.println(hashSet.isEmpty());
//4.删除元素
hashSet.remove("张杰");
System.out.println("元素个数:"+hashSet.size());
hashSet.clear();//清空
}
}
实例二
自定义Person类(TreeSet的实例中也用到了该类,下面不再重复)
package com.collection.set;
import java.util.Objects;
public class Person implements Comparable<Person> {//实现该接口,是用TreeSet存储时必须要做的
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) {//重写equals()
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() {//重写hashCode()
int n1 = this.name.hashCode();
int n2 = this.age+31;//+31是因为31是一个质数,减少散列冲突,提高执行效率(系统自动重写时会在这里+31)
return n1 + n2;
}
@Override
public int compareTo(Person o) {//重写compareTo()
int n1 = this.name.compareTo(o.getName());
int n2 = this.age - o.getAge();
return n1==0?n2:n1;
}
}
实例二的测试类
package com.collection.set;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet的使用二
* 存储过程:
* (1)根据hashcode计算要保存的位置,若此位置为空则直接保存,不为空执行第二步;
* (2)执行equals()方法,如果equals()方法为true则认为重复,否则形成链表
*/
public class Demo03 {
public static void main(String[] args) {
Person p1 = new Person("刘洪",20);
Person p2 = new Person("李芳",23);
Person p3 = new Person("赵亮",19);
//1.创建集合
HashSet<Person> hashSet = new HashSet<>();
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
System.out.println("元素个数:"+hashSet.size());
//2.遍历元素
//2.1通过增强for
System.out.println("-----增强for-----");
for (Person person : hashSet) {
System.out.println(person);
}
//2.2通过迭代器
System.out.println("-----迭代器-----");
Iterator<Person> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//3.判断
System.out.println(hashSet.contains(p1));
System.out.println(hashSet.isEmpty());
//4.删除元素
hashSet.remove(new Person("刘洪",20));//重写了equals和hashCode方法,因此此处可以删除
System.out.println("元素个数:"+hashSet.size());
}
}
TreeSet
实例一
package com.collection.set;
import java.util.Iterator;
import java.util.TreeSet;
/**
* TreeSet的使用一
* 存储结构:红黑树
* 实现了SortedSet接口,对集合元素自动排序
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
TreeSet<String> treeSet = new TreeSet<>();
//1.添加元素
treeSet.add("hello");
treeSet.add("world");
treeSet.add("java");
System.out.println("元素个数:"+treeSet.size());
System.out.println(treeSet);
//2.遍历元素
//2.1增强for
System.out.println("-----增强for-----");
for (String s : treeSet) {
System.out.println(s);
}
//2.2迭代器
System.out.println("------迭代器-----");
Iterator<String> it = treeSet.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
System.out.println("-----------------");
//3.判断
System.out.println(treeSet.contains("hello"));
System.out.println(treeSet.isEmpty());
//4.删除元素
treeSet.remove("hello");
System.out.println("元素个数:"+treeSet.size());
}
}
实例二(Person类在前面)
package com.collection.set;
import java.util.TreeSet;
/**
* TreeSet的使用二
* 要求:元素必须实现Comparable接口,compareTo()方法返回值为0时则认为是重复元素
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
TreeSet<Person> personTreeSet = new TreeSet<>();
//Person类要实现Comparable接口,否则添加元素时出现ClassCastException
//1.添加元素
Person p1 = new Person("刘洪",20);
Person p2 = new Person("李芳",23);
Person p3 = new Person("赵亮",19);
personTreeSet.add(p1);
personTreeSet.add(p2);
personTreeSet.add(p3);
System.out.println("元素个数:"+personTreeSet.size());
System.out.println(personTreeSet.toString());
//2.遍历元素,两种方法
//3.判断
//4.删除元素
personTreeSet.remove(new Person("赵亮",19));//这样也可以删除,因为是通过compareTo()比较元素是否重复
System.out.println(personTreeSet);
}
}
实例三:Comparator接口实现定制比较
package com.collection.set;
import java.util.Comparator;
import java.util.TreeSet;
/**
* Comparator接口:实现定制比较(比较器)
*/
public class Demo06 {
public static void main(String[] args) {
Person p1 = new Person("刘洪",20);
Person p2 = new Person("李芳",23);
Person p3 = new Person("赵亮",19);
//创建集合时就制定比较规则
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;
}
});
persons.add(p1);
persons.add(p2);
persons.add(p3);
System.out.println("元素个数:"+persons.size());
System.out.println(persons.toString());
}
}
实例四:通过Comparator比较器实现将字符串按照长度大小排序放入集合
package com.collection.set;
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("abc");
treeSet.add("xyz");
treeSet.add("hello");
treeSet.add("world");
treeSet.add("java");
treeSet.add("javac");
treeSet.add("yours");
System.out.println(treeSet);
}
}
Map接口
特点
- 用于存储任意键值对(key-value);
- 键:无序、无下标、不可重复;
- 值:无序、无下标、允许重复。
实例
package com.collection.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<String,String> map = new HashMap<>();
//1.添加元素
map.put("apple","苹果");
map.put("banana","香蕉");
map.put("mango","芒果");//如果key重复,则会覆盖之前添加的元素
System.out.println("元素个数:"+map.size());
System.out.println(map);
//2.遍历元素
//2.1通过keySet()方法
System.out.println("-----keySet()方法-----");
//Set<String> set = map.keySet();
for (String s : map.keySet()) {
System.out.println(s+"="+map.get(s));
}
//2.2通过entrySet()方法
System.out.println("-----entrySet()方法-----");
//Set<Map.Entry<String,String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey()+"="+entry.getValue());
}
//3.判断
System.out.println(map.containsKey("apple"));
System.out.println(map.containsValue("梨子"));
System.out.println(map.isEmpty());
//4.删除
map.remove("apple");
System.out.println("元素个数:"+map.size());
System.out.println(map);
}
}
Map接口的实现类
HashMap类
-
线程不安全,运行效率快;允许用null作为key/value;
-
存储结构:哈希表(数组+链表+红黑树);
-
使用key值的hashCode和equals()判断重复;
-
默认容量为10.
-
对HashMap源码分析总结
- HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16;
- 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍,目的是减少调整元素的个数;
- JDK1.8当每个链表长度大于8,且数组元素个数大于64时,会调整为红黑树,目的是提高执行效率;
- JDK1.8当链表长度小于6时,调整为链表;
- JDK1.8以前,链表为头插入,之后为尾插入;
- HashSet实际是HashMap的key来保存元素。
HashTable类
- 线程安全,效率慢,不允许null作为key/value;
- 子类:Properties,要求key和value都是String类型,通常用于配置文件的读取;
- 现在这个类不常用了。
TreeMap类
- 实现了SortedMap接口,可以对key自动排序;
- 存储结构:红黑树;
- 要求:key要实现Comparable接口,compareTo()返回为0时认为是重复元素;
- 可以定制比较器Comparator接口,创建集合时定制比较规则;
- TreeSet实际是用TreeMap的key保存数据。
HashMap
实例
下面例子中会用到的Student类
package com.collection.map;
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 this.stuNo;
}
}
测试类
package com.collection.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* HashMap的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 使用key值的hashcode和equals判断重复
*/
public class Demo02 {
public static void main(String[] args) {
//创建学生对象
Student s1 = new Student("张三",101);
Student s2 = new Student("李四",102);
Student s3 = new Student("王五",103);
//创建集合
HashMap<Student,String> students = new HashMap<>();
//1.添加元素
students.put(s1,"上海");
students.put(s2,"北京");
students.put(s3,"上海");
//students.put(new Student("王五",103),"上海");
System.out.println("元素个数:"+students.size());
System.out.println(students);
//2.遍历元素
//2.1keySet()方法
System.out.println("-----keySet()方法-----");
for (Student student:students.keySet()) {
System.out.println(student+"="+students.get(student));
}
//2.2entrySet()方法
System.out.println("-----entrySet()方法-----");
for (Map.Entry<Student,String> entry:students.entrySet()) {
System.out.println(entry.getKey()+"="+entry.getValue());
}
//3.判断
System.out.println(students.containsKey(new Student("王五",103)));
System.out.println("深圳");
//4.删除
students.remove(s1);
System.out.println("元素个数:"+students.size());
}
}
TreeMap
实例
package com.collection.map;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
/**
* TreeMap的使用
* 存储结构:红黑树
* 要求:key要实现Comparable接口,compareTo()返回为0时认为是重复元素
* 如果没有实现该接口也可以自己通过Comparator接口定制比较器
*/
public class Demo03 {
public static void main(String[] args) {
Student s1 = new Student("张三",101);
Student s2 = new Student("李四",102);
Student s3 = new Student("王五",103);
//通过比较器实现比较
TreeMap<Student,String> students = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getStuNo() - o2.getStuNo();
}
});
//1.添加元素
students.put(s1,"上海");
students.put(s2,"北京");
students.put(s3,"南京");
System.out.println("元素个数:"+students.size());
System.out.println(students);
//2.遍历元素
//2.1keySet()方法
System.out.println("------keySet()方法--------");
for (Student student:students.keySet()) {
System.out.println(student+"="+students.get(student));
}
//2.2entrySet()方法
System.out.println("------entrySet()方法--------");
for (Map.Entry<Student,String> entry:students.entrySet()) {
System.out.println(entry.getKey()+"="+entry.getValue());
}
//3.判断
System.out.println(students.containsKey(s1));
//4.删除元素
students.remove(s1);
System.out.println("元素个数:"+students.size());
}
}
Collections工具类
概念
集合工具类,定义了除存储之外的集合常用方法
常用方法
- public static void reverse(List<?> list) 反转集合中的元素
- public static void shuffle(List<?> list) 随机重置集合元素的顺序
- public static void sort(List<?> list) 升序排序(元素类型必须实现Comparable接口)
- binarySearch(…) 排序之后可进行二分查找
- copy()复制
实例
package com.collection.map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Collections工具类的使用
*/
public class Demo04 {
public static void main(String[] args) {
//创建集合
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(30);
list.add(70);
list.add(1);
list.add(8);
list.add(100);
list.add(13);
System.out.println("排序之前:");
System.out.println(list);
System.out.println("排序之后:");
Collections.sort(list);
System.out.println(list);
//binarySearch()排序后可以通过该方法进行二分查找
int n = Collections.binarySearch(list,1);
System.out.println("1的下标:"+n);
//copy()复制,必须先保证两个集合的长度一样
List<Integer> list1 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
list1.add(i);
}
Collections.copy(list1,list);
System.out.println(list1);
//reverse()反转集合
Collections.reverse(list);
System.out.println(list);
//shuffle()打乱
Collections.shuffle(list);
System.out.println(list);
//补充:list-->数组
Integer[] arr = list.toArray(new Integer[10]);
System.out.println("数组长度"+arr.length);
System.out.println(Arrays.toString(arr));
//数组-->集合
//转成的集合是一个受限集合,不能增加和删除元素
String[] arr1 = {"张三","李四","王五","刘英"};
List<String> list2 = Arrays.asList(arr1);
System.out.println(list2);
//list2.add("liu"); UnsupportedOperationException
//list2.remove("张三"); UnsupportedOperationException
//基本类型的数组转成集合时要用包装类,装箱
Integer[] nums = {12,22,30,39};
List<Integer> list3 = Arrays.asList(nums);
System.out.println(list3);
}
}