3-Java集合框架详解 通俗易懂
集合的概念:对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能
和数组区别:1、数组长度固定,集合长度不固定2,数组可以放基本类型和引用类型,集合只能放引用类型
位置:java.util
Collection体系集合

Collection父接口
package operator;
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 coll = new ArrayList();//父类引用,Collection接口和子接口list和set都不能实例化,只能用ArrayList实例化
//添加元素
coll.add("apple");//其实用的就是ArrayList的add方法,重写了父类Collection的add方法
coll.add("banana");
coll.add("orange");
coll.add("grape");
System.out.println(coll.size());//4
System.out.println(coll);//[apple, banana, orange, grape]
//删除元素
coll.remove("banana");
System.out.println(coll.size());//3
//遍历元素1,增加for
for (Object obj : coll) {
System.out.println(obj);
//apple
//orange
//grape
}
//遍历元素2,使用迭代器(迭代器专门用来遍历集合的元素)
//hasNext()方法判断有没有下一个元素
//next()方法获取下一个元素
//remove()方法删除当前元素
Iterator it = coll.iterator();//Collection中的方法iterator(),获取一个 Iterator 对象。Iterator 对象可以用来遍历集合中的元素。Iterator 是一个接口,定义了遍历集合的方法。
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
//迭代器不能用collections.remove()方法删除元素,只能用迭代器的remove()方法删除元素
//it.remove();
}
//判断元素是否存在
System.out.println(coll.contains("apple"));//true
}
}
案例,定义一个学生类
package operator;
public class Student {
private String name;
private int age;
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 operator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Demo02 {
//Collection的使用,保存学生信息
public static void main(String[] args) {
//创建Collection集合对象
Collection collection = new ArrayList();
//1,添加数据
Student student1 = new Student("张三", 20);
Student student2 = new Student("王五", 22);
Student student3 = new Student("李四", 22);
collection.add(student1);
collection.add(student2);
collection.add(student3);
System.out.println(collection.size());//3
System.out.println(collection.toString());//[Student[name=张三, age=20], Student[name=王五, age=22], Student[name=李四, age=22]]
//collection.clear();,删除之后 ,其实三个对象还在,
//2,遍历集合
for (Object obj : collection) {
Student student = (Student) obj;
System.out.println(student.getName() + " " + student.getAge());
}
//迭代器
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
Student student = (Student) iterator.next();
System.out.println(student.getName() + " " + student.getAge());
//张三 20
//王五 22
//李四 22
}
}
}
List集合-List子接口
特点:有序,有下标,元素可以重复
package operator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
//List子接口
//特点:有序,有下标,元素可重复,
public class Demo03 {
public static void main(String[] args) {
//先创建集合对象
List list = new ArrayList();
//添加元素
list.add("apple");
list.add("banana");
list.add(0,"orange");
System.out.println(list.toString());
//删除元素
list.remove(1);
System.out.println(list.toString());
//遍历
//for
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//增加for
for (Object obj : list) {
System.out.println(obj);
}
//迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//使用列表迭代器,和Iterator的区别,listIterator可以向前或向后遍历,添加,删除,修改元素
ListIterator list1 = list.listIterator();
while (list1.hasNext()) {
System.out.println(list1.nextIndex() + " " + list1.next());//从前往后
}
//0 orange
//1 banana
while(list1.hasPrevious()){
System.out.println(list1.previousIndex()+" "+list1.previous());//从后往前
//1 banana
//0 orange
}
//判断
System.out.println(list.contains("banana"));//true
//获取位置
System.out.println(list.indexOf("banana"));//1
}
}
package operator;
import java.util.ArrayList;
import java.util.List;
public class Demo04 {
public static void main(String[] args) {
List List = new ArrayList();
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());//[20, 30, 40, 50, 60]
//删除操作,两种方法,list.remove(0)
List.remove(new Integer(20));//数字转成Integer对象
System.out.println(List.toString());//[30, 40, 50, 60]
//补充方法sublist,返回子集合,含头不含尾
List<Integer> subList = List.subList(1, 3);
System.out.println(subList.toString());//[40, 50]
List实现类

ArrayList的使用
package operator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
//ArrayList的使用
//存储结构:数组、查找遍历速度快、增删慢
public class Demo05 {
public static void main(String[] args){
ArrayList list = new ArrayList();
//添加元素
Student s1=new Student("张三", 20);
Student s2=new Student("李四", 22);
Student s3=new Student("王五", 27);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println(list.size());
System.out.println(list.toString());
//删除元素
list.remove(s2);
System.out.println(list.size());//2
System.out.println(list.toString());//[Student[name=张三, age=20], Student[name=王五, age=27]]
//遍历元素
//使用迭代器
Iterator iterator = list.iterator();
while(iterator.hasNext()){
Student s = (Student)iterator.next();
System.out.println(s.toString());
}
//Student[name=张三, age=20]
//Student[name=王五, age=27]
//列表迭代器
ListIterator listIterator = list.listIterator();
while(listIterator.hasNext()){
Student s = (Student)listIterator.next();
System.out.println(s.toString());
}
//Student[name=张三, age=20]
//Student[name=王五, age=27]
while(listIterator.hasPrevious()){
Student s = (Student)listIterator.previous();
System.out.println(s.toString());
}
//Student[name=王五, age=27]
//Student[name=张三, age=20]
//
}
}
ArrayList源码分析
private static final int DEFAULT_CAPACITY = 10;默认容量大小为10;注意:如果没有向集合中添加任何元素时,容量为0,添加一个元素之后,容量为10,要回到源码去看
每次扩容大小是原来的1。5倍
transient Object[] elementData;存放元素的数组
private int size;实际的元素的个数
Vector-开发用得不是特别多,了解即可
数组结构实现、查询快、增删慢
JDK1。0版本,运行效率慢、线程安全
package operator;
import java.util.Enumeration;
import java.util.Vector;
//Vector
//存储结构:数组
public class Demo01 {
public static void main(String[] args) {
Vector vector = new Vector();
//添加元素
vector.add("苹果");
vector.add("芒果");
vector.add("香蕉");
System.out.println(vector.size());
//删除
//vector.remove(1);
//vector.remove("苹果");
//vector.clear();
//遍历
//特有的方法,枚举器
Enumeration en = vector.elements();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
//其他方法
System.out.println(vector.firstElement());
}
}
LinkedList
链表结构实现,增删快,查询慢
package operator;
//LinkList的使用
//存储结构:双向链表
import java.util.Iterator;
import java.util.LinkedList;
public class Demo01 {
public static void main(String[] args) {
//创建集合
LinkedList list = new LinkedList<>();
//添加元素
Student s1 = new Student("张三", 20);
Student s2 = new Student("李四", 20);
Student s3= new Student("王五", 20);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println(list.size());
//删除
list.remove(s2);
System.out.println(list.size());
//遍历
for (Object obj : list) {
Student s = (Student) obj;
System.out.println(s.getName() + " " + s.getAge());
}
//使用迭代器
Iterator it = list.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
System.out.println(s.getName() + " " + s.getAge());
}
}
}
源码分析
不同结构实现方式

泛型
和之前的类差不多,只是之前的类参数是基本类型,现在是引用类型

泛型类
package operator;
//泛型类
//语法:类名<T>,T取绝你希望是什么引用类型,如果要String,就用String
//T是类型点位符,表示一种引用类型,如果写多个就用逗号隔开
//**如果在new对象时,已经把参数类型定为String,那下面的方法show就不能传入111,会报错,除非在new对象时,没写t的类型,那上面方法show,你传什么类型进去,print就会输出什么类型**
//**所以下面的泛型集合,就是在new的时候,如果已经传入类型,那下面的方法,基本都会限制为你传入的类型**
public class MyGeneric<T> {
//使用泛型T
//创建变量
T t;
//泛型作为方法的参数
public void show(T t) {
System.out.println(t);
}
//泛型作为方法的返回值
public T get(T t) {
return t;
}
}
package operator;
public class TestGeneric {
public static void main(String[] args) {
//使用泛型类创建对象
//1、泛型只能使用引用类型 2、不同的泛型类型对象,不能相互赋值
MyGeneric<String> myGeneric = new MyGeneric();//创建MyGeneric对象,泛型类型为String,String是自己定义的
myGeneric.t="Hello World";//给MyGeneric对象赋值
myGeneric.show("大家好");
String str = myGeneric.get("你好你好");
System.out.println(str);
MyGeneric<Integer> myGeneric2 = new MyGeneric<>();//创建MyGeneric对象,泛型类型为Integer
myGeneric2.t=100;
myGeneric2.show(200);
//大家好
//你好你好
//200
}
}
泛型接口
定义接口
package operator;
//泛型接口
//语法:接口名
//注意,不能创建泛型静态常量
public interface MyInterface<T> {
String name="张三";
T server(T t);
}
两种写法,已经确定接口类型的
package operator;
//实现接口时就要把类固定了
public class MyInterfaceImpl implements MyInterface<String> {
@Override
public String server(String s) {
System.out.println(s);
return s;
}
}
还没确定接口类型
package operator;
//如果不想那么快就定义接口的类型时,实现类也加上类型参数
public class MyInterfaceImpl2<T> implements MyInterface<T> {
@Override
public T server(T t) {
System.out.println(t);
return t;
}
}
package operator;
public class TestGeneric {
public static void main(String[] args) {
MyInterfaceImpl myInterface = new MyInterfaceImpl();
myInterface.server("Hello");//Hello
MyInterfaceImpl2<Integer> myInterface2 = new MyInterfaceImpl2();
myInterface2.server(100);//100
}
}
泛型方法
方法定义
package operator;
//泛型方法
//语法:<T>返回值
public class MyGenericMethod {
//泛型方法
public <T> T show(T t) {
System.out.println("泛型方法"+t);
return t;
}
}
package operator;
public class TestGeneric {
public static void main(String[] args) {
MyGenericMethod gg = new MyGenericMethod();
gg.show("中国加油");//中国加油,类型是String
gg.show(100);//100,类型是Integer
}
}
泛型的好处,
1、提高代码的重用性-不用重写,一个方法就可以传递不同类型的参数,不用像以前一样要重载多个方法
2、防止类型转换异常,提高代码的安全性
泛型集合
LinkedList list = new LinkedList<>();
public class LinkedList
当什么类型都没传参时,默认是object,所以往里面加什么元素时,都会默认转化成object类型

package operator;
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("aaa");
arrayList.add("bbb");
arrayList.add(10);
for (Object obj : arrayList) {
System.out.println(obj);
}//不会报错
for(Object obj : arrayList){
String str = (String) obj;
System.out.println(str);//会报错,10无法强转为String类型
}
}
package operator;
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("aaa");
arrayList.add("bbb");
// arrayList.add(10);加上String后,编译时这里就会标红了,提示你要修改
for (String str : arrayList) {
System.out.println(str);
}
ArrayList<Student> arrayList2 = new ArrayList<Student>();
arrayList2.add(new Student("Tom", 20));
arrayList2.add(new Student("Jerry", 25));
for (Student student : arrayList2) {
System.out.println(student.getName() + " " + student.getAge());
}
//aaa
//bbb
//Tom 20
//Jerry 25
}
}
Set子接口
特喽:无序,无下标,元素不可重复
方法:全部继承Collection的方法
package base;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* set接口的使用
*特点:无序,没有下标,元素不能重复
*
*/
public class Demo01 {
public static void main(String[] args) {
// 创建set集合
Set<String> set = new HashSet<>();
// 添加元素
set.add("apple");
set.add("banana");
set.add("orange");
set.add("orange");
System.out.println(set.size());
System.out.println(set.toString());//[banana, orange, apple]无序,加多了的orange会自动去掉
//删除
set.remove("banana");
System.out.println(set.toString());//[orange, apple]
//遍历
for (String str : set) {
System.out.println(str);
}
//迭代器
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//判断是否包含元素
System.out.println(set.contains("apple"));//true
}
}
HashSet-重点
1、基于Hashcode计算元素存放位置(就算重写hashcode方法,不同属性的对象仍可能存在相同hashcode,一般相同hashcode,就已经拒绝存入了,所以需要equals进行二次判断)
2、当存入元素哈希码相同时,会调用equals进行确认,如果为true,则拒绝后者存入(set是不允许重复元素)
知识补充
==和equals方法的区别,为什么重写equals还要重写hashCode?
HashSet集合中元素的添加过程
1、== 运算符
使用范围:基本数据类型和引用数据类型。
在基本数据类型中:比较的是两个变量保存的数据是否相等。
在引用数据类型中:比较的是两个对象的地址是否相同,即两个引用对象是否指向同一个对象实体。
在没有重写equals方法前,equals 和 == 都是一样的,都是比较对象的引用是否相同。(对象的内存地址)
2、每个对象都有一个默认的hashCode实现,它通常是根据对象的内存地址计算出的一个唯一标识。不同对象的 hashCode 可能相同;但 hashCode 不同的对象一定不相等。(所以hashcode不是对象的内存地址)-所以为什么不能用object的hashcode方法,他的方法就是根据内存地址计算,所以就算两个属性相同的new出来的,也会判定为不同的对象,所以要重新写hashcode方法,至少让两个对象相等先,才能走到equals方法,equals的原方法也是比较两个对象的内存地址,也是不行的,所以要重写equals方法
public boolean equals(Object obj) {
return (this == obj);
}
3、添加元素的过程:
我们向HashSet中添加元素a,首先会调用元素a所在类的hashCode()方法,计算元素a的hash值(哈希值),之后再根据得到的元素a的hash值再通过散列函数(一种算法,我们可以通过这个算法得到我们元素a在数组中应该存储的索引位置)计算出在我们的元素a在底层数组中的存放位置(也就是索引位置),再判断这个位置上是否已经有了元素了
如果此位置上没有其他元素,则元素a添加成功 ---- 情况一
如果此位置上有其他元素b(或者以链表形式存在的多个元素),则比较元素a与元素b的hash值
如果元素a和元素b的哈希值不相同,则元素a添加成功 ---- 情况二
如果元素a和元素b的哈希值相同,进而需要调用元素a所在类的equals()方法判断
如果equals()方法返回false,则元素a添加成功 ---- 情况三
如果equals()方法返回true,则元素a添加失败
4、易错点避免:
两个不同的对象,这两个不同的对象的hash值有可能是相同的
两个相同的对象,这两个对象的hash值就一定是相同的
这个就说明我们在HashSet中添加元素时即使我们的元素的索引位置相同,并且hash值也相同,也有可能不是同一对象,这个时候我们还要通过使用equals()方法判断是否是真正的同一个对象
不同的两个hash值通过散列函数计算的数组的索引位置可能相同
也就是当我们的HashSet中底层的数组中的同一索引位置中的元素可能是不同的hash值的对象,这个时候我们就要在判断一下同一位置上的元素的hash值是否相同
import java.util.HashSet;
/**
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 特点:无序、唯一
*/
public class Demo02 {
public static void main(String[] args) {
// 创建HashSet集合
HashSet<String> set = new HashSet<>();
// 添加元素
set.add("apple");
set.add("banana");
set.add("orange");
set.add("pear");
System.out.println(set.toString());
}
}
package base;
import java.util.Objects;
public class 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 int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Name: " + name + ", Age: " + age;
}
@Override
public int hashCode() {
int n1=this.name.hashCode();//调用的是String的hashCode方法,其算法是基于字符串中每个字符的Unicode值来进行的
int n2=this.age;
return n1+n2;
}
@Override
public boolean equals(Object obj) {//Object obj是指Hashset中已存放的对象,会把新对象和已存对象进行比较
//// 比较当前对象与传入对象是否为同一对象
if(this==obj){
return true;
}
if(obj==null){
return false;
}
if(obj instanceof Person){
Person p=(Person)obj;
if(this.name.equals(p.name) && this.age==p.age){
return true;
}
}
return false;
}
}
可以利用生成方法,快速重写hashcode和equals方法,重写这两个方法是避免添加重复属性的对象
package base;
import java.util.HashSet;
import java.util.Iterator;
/**
* HashSet集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 特点:无序、唯一
* 存储过程
* 根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
* 再执行equals方法(判断两个对象hashcode是否相等),如果为true,则认为重复,否则形成链表
*/
public class Demo02 {
public static void main(String[] args) {
// 创建HashSet集合
HashSet<Person> set = new HashSet<>();
// 添加元素
Person p1 = new Person("Jeff", 27);
Person p2 = new Person("Jerry", 25);
Person p3 = new Person("Tom", 20);
Person p4 = new Person("Tom", 20);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(p4.hashCode());
System.out.println(p3.hashCode());
set.add(new Person("Tom", 20));//如果不重写equals方法,虽然 hashCode 相同,但是会在同一个位置形成链表,从而加进来,如果要判定这个是重复元素不让加入,需要重写 equals 方法
//add方法会自动调用Person类中的hashCode和equal方法
System.out.println(set.size());
System.out.println(set.toString());
/**
* 为了确定这个新对象是否已经是集合中的成员,Set会调用以下方法:
* new Person("Tom", 20).hashCode():计算新对象的哈希码。如果不重写hashCode方法,默认的hashCode方法是基于对象的内存地址,就算两个对象有相同的属性,也可能得到不同的hashCode。
* 对于哈希码相同的每个对象(在Set中可能有多个对象,因为哈希码碰撞是可能的),Set会调用equals方法来比较新对象和已存在的对象。
* 如果Person类没有重写hashCode和equals方法,那么equals方法默认是比较两个对象的引用是否相同。因此,即使两个Person对象的属性相同(名字和年龄都是"Tom"和20),只要它们是不同的对象(不同的引用),它们也会被视为不同的元素。
* 在你的代码示例中,p3和p4虽然有相同的属性,但由于它们是不同的对象,如果没有重写equals方法,p4仍然会被添加到集合中,使得集合的大小增加。
* 因此,set.add(new Person("Tom", 20))这行代码会使用equals方法来比较新创建的Person("Tom", 20)对象和集合中已经存在的每个Person对象,以确定是否应该将其添加到集合中。如果你希望具有相同属性的对象被视为相同,你需要重写Person类的hashCode和equals方法。
*/
//遍历
for (Person person : set) {
System.out.println(person.toString());
}
//迭代器
Iterator<Person> iterator = set.iterator();
while (iterator.hasNext()) {
Person person = iterator.next();
System.out.println(person.toString());
}
}
}
TreeSet
1、基于排列顺序实现元素不重复
2、实现了SortedSet接口,对集合元素自动排序
3、元素对象的类型必须实现Comparable接口,指定排序规则
4、通过CompareTo方法确定是否为重复元素
二叉树:左小右大
红黑树:根节点是黑(在二叉树的基础再加颜色),节点有黑有红,就是为了保证结构平衡

package base;
import java.util.TreeSet;
/**
* TreeSet使用
* 存储结构:红黑树
*/
public class Demo04 {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<>();
set.add("xyx");
set.add("abc");
set.add("hello");
System.out.println(set.size());
System.out.println(set.toString());//[abc, hello, xyx],按字母顺序排列
}
}
package base;
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 int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Name: " + name + ", Age: " + age;
}
//先按姓名比,然后再按年龄比
@Override
public int compareTo(Person o) {
int n1=this.getName().compareTo(o.getName());
int n2=this.getAge()-o.getAge();
return n1==0?n2:n1;
}
}
package base;
import java.util.TreeSet;
//要求:元素必须实现Comparable接口,并重写compareTo()方法,以便排序。否则再add()时会报错。compareTo()方法返回值为0,认为是重复元素
public class Demo05 {
public static void main(String[] args) {
TreeSet<Person> persons = new TreeSet<>();
persons.add(new Person("John", 25));
persons.add(new Person("Alice", 30));
persons.add(new Person("Bob", 20));
System.out.println(persons.size());
System.out.println(persons.toString());
}
}
另一种写法Comparator接口
package base;
import java.util.Comparator;
import java.util.TreeSet;
//TreeSet集合的使用
//Comparator:实现定制比较(比较器)
//Comparable:可比较的
public class Demo05 {
public static void main(String[] args) {
TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
//new Comparator<Person>():因为Person类没有实现Comparable接口,这里需要提供一个Comparator来定义排序规则
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getName().compareTo(o2.getName());
int n2 = o1.getAge() - o2.getAge();
return n1 != 0 ? n1 : n2;
}
});
persons.add(new Person("John", 25));
persons.add(new Person("Alice", 30));
persons.add(new Person("Bob", 20));
System.out.println(persons.size());
System.out.println(persons.toString());
}
}
Map集合
HashMap-重点


package Map;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 特点:键值对存储,无序性,键唯一,值可重复
*/
public class Demo01 {
public static void main(String[] args) {
// 创建Map对象
HashMap<String, String> map = new HashMap<>();
//添加元素
map.put("cn", "中国");
map.put("uk", "英国");
map.put("usa", "美国");
map.put("cn", "zhongguo");//{usa=美国, uk=英国, cn=zhongguo}
System.out.println(map.size());
System.out.println(map.toString());//{usa=美国, uk=英国, cn=中国}
//删除
map.remove("cn");
System.out.println(map.size());//2
//遍历
//使用keySet()
Set<String> keyset = map.keySet();
for (String key : keyset) {//也能写成for(String key : map.keySet())
System.out.println(key);
System.out.println(map.get(key));
}
//使用entrySet()
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
}
}

package Map;
import java.util.HashMap;
/**
* HashMap集合的使用
* 存储结构 :哈希表(数组+链表+红黑树)
* 使用key可hashcode和equals作为重复,要重写这两个方法
*/
public class Demo02 {
public static void main(String[] args) {
HashMap<Student, String> students = new HashMap<>();
Student s1 = new Student("张三", 100);
Student s2 = new Student("李四", 101);
Student s3 = new Student("王五", 102);
students.put(s1, "北京");
students.put(s2, "上海");
students.put(s3, "深圳");
//students.put(new Student("李四", 101), "广州"); // 要重写hashcode和equals方法,才能保证不会加入重复的new对象
System.out.println(students.size());
System.out.println(students.toString());
}
}

Hashtable 较少用了
Properties 上面的子类,流的时候会用,通常用于配置文件的读取
TreeMap 实现了SortedMap接口(是Map的子接口)可以对key自动排序
package Map;
import java.util.TreeMap;
/**
* TreeMap
* 存储结构:红黑树
*
*/
public class Demo03 {
public static void main(String[] args) {
TreeMap<Student, String> treeMap = new TreeMap<Student, String>();
Student s1 = new Student("张三", 100);
Student s2 = new Student("李四", 101);
Student s3 = new Student("王五", 102);
treeMap.put(s1, "北京");
treeMap.put(s2, "上海");
treeMap.put(s3, "深圳");
System.out.println(treeMap.size());//要继承Comparable接口才能排序
System.out.println(treeMap.toString());
}
}
Collections工具类
除了存取以外常用的集合常用方法
package Map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.binarySearch;
/**
- 演示Collections工具类的使用
*/
public class Demo04 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(120);
list.add(30);
list.add(50);
list.add(20);
list.add(40);
//sort方法
System.out.println("排序前:" + list);//排序前:[120, 30, 50, 20, 40]
Collections.sort(list);
System.out.println("排序后:" + list);//排序后:[20, 30, 40, 50, 120]
//binarySearch方法
int i=Collections.binarySearch(list, 30);
System.out.println("查找30的索引:" + i);//1
//copy,这个方法有问题,不用
//ArrayList<Integer> list2 = new ArrayList<>();
//Collections.copy(list2, list);
//System.out.println("复制后:" + list2);//复制后:[20, 30, 40, 50, 120]
//reverse
Collections.reverse(list);
System.out.println("反转后:" + list);//反转后:[120, 50, 40, 30, 20]
//shuffle
Collections.shuffle(list);
System.out.println("打乱后:" + list);//打乱后:[20, 30, 50, 120, 40]
//补充:list转数组-指的是list接口-转后就可以直接使用数组的操作方法
Integer[] arr = list.toArray(new Integer[10]);
System.out.println("转数组后:" + Arrays.toString(arr));//转数组后:[40, 120, 50, 20, 30, null, null, null, null, null]
System.out.println(arr.length);//10
//数组转成集合
String[] name = {"apple", "banana", "orange", "pear"};
//集合是一个受限集合,不能添加和删除元素,只能读取元素
List<String> list1 = Arrays.asList(name);
System.out.println(list1); //[apple, banana, orange, pear]
//基本类型数组转集合,需要修改为包装类型
Integer[] arr1 = {1, 2, 3, 4, 5};
}
}
数组和集合的区别
数组存放基本类型和引用类型,一旦创建了长度就不能变了,大小不能更改
集合主要是存放引用类型数据,可以随时加入元素


浙公网安备 33010602011771号