定义:集合是对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能。
对比数组的区别
位置:Java.until.*
Colletion
List(有序的,有下标,元素可重复)
Set(无序的,无下标,元素不能重复)
特点:代表一组任意类型的对象,无序,无下标,不能重复。
方法
为什么不用普通的for而用增强型for
for遍历是需要下标的,collection又没有下标,只能使用增强for
/**
* 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);
System.out.println("===========================");
//2、删除元素
// collection.remove("苹果");
// collection.clear();
System.out.println("元素的个数" + collection.size());
System.out.println("===========================");
//3、遍历元素
//3.1增强型for循环
for (Object object:collection) {
System.out.println(object);
}
System.out.println("===========================");
//3.2使用迭代器(是专门用来迭代集合的一种方法)
//迭代器下面有hasNext()、next()、remove()这三种方法
//hasNext()是否有下一个元素
//next()获取元素
//remove()删除一个元素
Iterator iterator = collection.iterator();
while (iterator.hasNext()){
// 强制转换类型
String ob = (String) iterator.next();
System.out.print(ob);
//不能使用collection的其他方法用来改变集合
//否则会出现并发修改异常Exception in thread "main" java.util.ConcurrentModificationException
// collection.remove("苹果");
iterator.remove();
}
System.out.println("元素的个数" + collection.size());
System.out.println("===========================");
//4、判断
System.out.println(collection.contains("西瓜"));
System.out.println(collection.isEmpty());
}
}
/**
* Collection:保存学生信息
*/
public class Demo02 {
public static void main(String[] args) {
Collection collection = new ArrayList();
Student s1 = new Student("Lee",11);
Student s2 = new Student("zhang",12);
Student s3 = new Student("wang",13);
//1、增加元素
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println("元素的个数"+collection.size());
System.out.println(collection.toString());
//2、删除元素
// collection.remove(s1);
==//思考?如何使用new的方式删除==
使用new Interger()
//删除只是删除地址,数据依然存在
// collection.clear();
// collection.remove(new Student("Lee",11));
System.out.println("元素的个数"+collection.size());
//3、遍历
//3.1 增强for
for (Object ob:collection) {
Student s =(Student) ob;
System.out.println(s.toString());
}
System.out.println("===========================");
//3.2 迭代器
Iterator it = collection.iterator();
while (it.hasNext()){
Student s = (Student)it.next();
System.out.println(s.toString());
}
//4、判断
System.out.println(collection.contains(s1));
//思考?new对象如何才能为true
System.out.println(collection.contains(new Student("Lee",11)));
System.out.println(collection.isEmpty());
}
}
特点:有序、有小标、元素可以重复
方法:API文档可查
/**
* Collection:保存学生信息
*/
public class Demo02 {
public static void main(String[] args) {
Collection collection = new ArrayList();
Student s1 = new Student("Lee",11);
Student s2 = new Student("zhang",12);
Student s3 = new Student("wang",13);
//1、增加元素
collection.add(s1);
collection.add(s2);
collection.add(s3);
System.out.println("元素的个数"+collection.size());
System.out.println(collection.toString());
//2、删除元素
// collection.remove(s1);
==//思考?如何使用new的方式删除==
使用new Interger()
//删除只是删除地址,数据依然存在
// collection.clear();
// collection.remove(new Student("Lee",11));
System.out.println("元素的个数"+collection.size());
//3、遍历
//3.1 增强for
for (Object ob:collection) {
Student s =(Student) ob;
System.out.println(s.toString());
}
System.out.println("===========================");
//3.2 迭代器
Iterator it = collection.iterator();
while (it.hasNext()){
Student s = (Student)it.next();
System.out.println(s.toString());
}
//4、判断
System.out.println(collection.contains(s1));
//思考?new对象如何才能为true
System.out.println(collection.contains(new Student("Lee",11)));
System.out.println(collection.isEmpty());
}
}
public class Demo02 {
public static void main(String[] args) {
//创建集合对象
List list = new ArrayList();
//增加元素
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
System.out.println("元素的个数:"+list.size());
System.out.println(list.toString());
System.out.println("=========================");
//删除元素
// list.remove(0);
//能够通过new 删除,是由于整数缓冲的原因
// list.remove(new Integer(20));
System.out.println("元素的个数:"+list.size());
System.out.println(list.toString());
System.out.println("=========================");
//补充方法subList,是含头不含尾
List list1 = list.subList(0,3);
System.out.println("元素的个数:"+list1.size());
System.out.println(list1.toString());
System.out.println("=========================");
}
}
ArrayList【重点】
数组结构实现,查询快,增删慢
JDK1.2版本出现,运行效率高,但是线程不安全
Vector
数组结构实现,查询快,增删慢
JDK1.0版本出现,运行效率低,但是线程安全
LinkedList:
链表结构实现,增删快,查询慢
/**
* ArrayList的使用
* 存储结构:数组,查找速度快,增删慢
*
*/
public class Demo05 {
public static void main(String[] args) {
//创建集合
ArrayList arrayList = new ArrayList<>();
//1、添加元素
Student s1 = new Student("A",97);
Student s2 = new Student("B",98);
Student s3 = new Student("C",99);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
//打印元素的长度和内容
System.out.println("元素的长度:"+arrayList.size());
System.out.println(arrayList.toString());
//2、删除元素
// arrayList.remove("20");
//在重构完equals后,不用写对象,就可以删除
// arrayList.remove(new Student("A",97));
// 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 列表迭代器
ListIterator lit = arrayList.listIterator();
System.out.println("--使用列表迭代器--");
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(s1));
System.out.println(arrayList.contains(new Student("A",97)));
System.out.println(arrayList.isEmpty());
//5、查找
System.out.println("---查找---");
System.out.println(arrayList.indexOf(s1));
System.out.println(arrayList.indexOf(new Student("A",97)));
}
}
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 +
'}';
}
//重构equals方法重构equals方法重构equals方法重构equals方法重构equals方法重构equals方法
@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;
}
}
//不满足条件返回false
return false;
}
}
ArrayList
DEFAULT_CAPACITY = 10;
//默认容量
//注意:如果没有向集合中添加任何元素时,容量0,添加一个后,容量为10
//每次扩容是原来的1.5倍
elementData存放元素的数组
size 实际元素个数
源码展示
//空数组
private static final int DEFAULT_CAPACITY = 10;
//空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//用来存放元素的数组
transient Object[] elementData; // non-private to simplify nested class access
//实际元素个数
private int size;
默认容量是10,指的是添加元素后,未添加则为0
重点add方法
public boolean add(E e) {
//增长修改个数
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//不知道为什么跟教程的源码不一样啊,但是也没差
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, 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);
}
两个知识点拓展
Arrays.copyOf(T[] original,int newLength ):拷贝数组,其内部调用了System.arrayCopy()方法,从下标0开始,如果超过原数组长度,会用null进行填充。
Arrays.copyOf()使用样例
Integer[] arr={1,2,3,4,5,6};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//拷贝数组arr1到长度为10的新数组中,
// 如果新数组长度大于arr1的长度,超过的部分用null填充
//如果新数组长度小于arr1的长度,只拷贝前几个数据
Integer[] arr2 = Arrays.copyOf(arr, 3);//arr2是{1,2,3}
Integer[] arr3 = Arrays.copyOf(arr, 10);//arr3是{1,2,3,4,5,6,null,null,null,null}
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
for (int i = 0; i < arr3.length; i++) {
System.out.println(arr3[i]);
}
/**
* Vector的使用
*/
public class Demo06 {
public static void main(String[] args) {
Vector vector = new Vector<>();
// 增
Student s1 = new Student("A",97);
Student s2 = new Student("B",98);
Student s3 = new Student("C",99);
vector.add(s1);
vector.add(s2);
vector.add(s3);
// 删
// vector.remove(s1);
// vector.remove(new Student("A",97));
// vector.clear();
// 遍历-枚举遍历
Enumeration en = vector.elements();
while (en.hasMoreElements()){
String o = (String) en.nextElement();
System.out.println(o);
}
// 判断
vector.contains(s1);
vector.contains(vector.isEmpty());
//还有很多其他方法,可以在JDK文档中查询
}
特点:链表结构、增删快、查询慢
/**
*LinkedList的使用
*/
public class Demp07 {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
Student s1 = new Student("A",97);
Student s2 = new Student("B",98);
Student s3 = new Student("C",99);
//增
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
System.out.println("长度:"+linkedList.size());
System.out.println(linkedList.toString());
//删
// linkedList.remove(s1);
// linkedList.remove(new Student("C",99));
// linkedList.clear();
//遍历
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
for (Object ob:linkedList) {
Student s = (Student)ob;
System.out.println(s.toString());
}
Iterator iterator = linkedList.listIterator();
while (iterator.hasNext()){
Student student = (Student) iterator.next();
System.out.println(student.toString());
}
ListIterator listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
Student student2 = (Student) listIterator.next();
System.out.println(student2.toString());
}
//判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
System.out.println(linkedList.indexOf(s1));
}
}
偷个懒,贴个链接,写的比我理解的好多了
LinkedList源码解析_以码为梯的博客-CSDN博客
ArrayList
LinkedList
思考为什么ArrayList的查询LinkedList比更快?
因为ArrayList开辟空间是连续的、而LinkedList不需要
Java是在JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递
常见的有泛型类、泛型接口、泛型方法
语法
T:tape 类型 E:element元素 K:key键值 V:value值 叫做类型占位符,表示一种引用类型。
好处:
/**
*LinkedList的使用
*/
public class Demp07 {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
Student s1 = new Student("A",97);
Student s2 = new Student("B",98);
Student s3 = new Student("C",99);
//增
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
System.out.println("长度:"+linkedList.size());
System.out.println(linkedList.toString());
//删
// linkedList.remove(s1);
// linkedList.remove(new Student("C",99));
// linkedList.clear();
//遍历
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
for (Object ob:linkedList) {
Student s = (Student)ob;
System.out.println(s.toString());
}
Iterator iterator = linkedList.listIterator();
while (iterator.hasNext()){
Student student = (Student) iterator.next();
System.out.println(student.toString());
}
ListIterator listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
Student student2 = (Student) listIterator.next();
System.out.println(student2.toString());
}
//判断
System.out.println(linkedList.contains(s1));
System.out.println(linkedList.isEmpty());
System.out.println(linkedList.indexOf(s1));
}
}
/**
* 泛型接口
* 语法:方法
*T表示类型占位符,表示一种引用类型,可编写多个用,隔开
*/
public interface MyInterface {
//不能泛型静态常量
String name = "牧之";
T server(T t);
}
public class MyInterfaceImpl implements MyInterface{
@Override
public String server(String t) {
System.out.println(t);
return t;
}
}
//在实现接口时,不确定泛型类型的操作
//将实现类也变成泛型类MyInterfaceImpl2
public class MyInterfaceImpl2 implements MyInterface{
@Override
public T server(T t) {
System.out.println(t);
return null;
}
}
//在实现接口时,不确定泛型类型的操作
//将实现类也变成泛型类MyInterfaceImpl2
public class MyInterfaceImpl2 implements MyInterface{
@Override
public T server(T t) {
System.out.println(t);
return null;
}
}
//泛型方法的使用
MyGenericmethod myGenericmethod = new MyGenericmethod();
//自动装箱,输入的类型是根据你传入的数据类型决定的
myGenericmethod.show("你好");
myGenericmethod.show(3);
myGenericmethod.show(3.14);
好处:提供代码的重用性
例如该段代码
//泛型方法的使用 MyGenericmethod myGenericmethod = new MyGenericmethod(); //自动装箱,输入的类型是根据你传入的数据类型决定的 myGenericmethod.show("你好"); myGenericmethod.show(3); myGenericmethod.show(3.14);
可以传入多个数据类型,如果是普通方法,会涉及到方法的重载
防止类型转换异常,提高代码的安全性
泛型对象之间不能相互赋值
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
特点:
/**
* 泛型集合
*/
public class Demo01 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("李冰");
arrayList.add("里牧之");
// arrayList.add(23);
// arrayList.add(24);
//ArrayList arrayList = new ArrayList();
//错误:java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
//当传入多种类型的数据,会出现类型转换异常
// for (Object o:arrayList) {
// String s = (String) o;
// System.out.println(s);
// }
for (String s:arrayList) {
System.out.println(s);
}
//可以通过泛型,输出多个不同的数据类型
ArrayList arrayList2 = new ArrayList();
Student s1 = new Student("A",97);
Student s2 = new Student("B",98);
Student s3 = new Student("C",99);
arrayList2.add(s1);
arrayList2.add(s2);
arrayList2.add(s3);
Iterator iterator = arrayList2.iterator();
while (iterator.hasNext()){
Student s = iterator.next();
System.out.println(s.toString());
}
}
}
特点:无序,无下标,元素不可重复
方法:均继承Collection接口
/**
* 测试Set的使用
* 特点:无序,无下标,元素不可重复
*/
public class Demo01 {
public static void main(String[] args) {
Set set = new HashSet();
//增加
set.add("张三");
set.add("李四");
set.add("王二");
//元素不能重复
// set.add("张三");
System.out.println(set.size());
System.out.println(set.toString());
//删除
// set.remove("张三");
// System.out.println(set.toString());
//遍历
//foreach
System.out.println("----------遍历------------");
for (String s : set) {
System.out.println(s);
}
//迭代器
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断
System.out.println(set.contains("张三"));
System.out.println(set.isEmpty());
}
}
新建集合 HashSet
添加元素 hashSet.add( );
删除元素 hashSet.remove( );
遍历操作
判断 hashSet.contains( ); hashSet.isEmpty();
/**
* HashSet集合的使用
* 存储结构:数组+链表+红黑树
* 存储过程:【重点】
* (1)根据hashcode计算保存位置,如果此位置为空(没有数据),直接保存,如果不为空,执行第二步
* (2)再执行equals方法,如为true,则认为是重复的,否则形成链表
*/
public class Demo03 {
public static void main(String[] args) {
//创建集合
HashSet hashSet = new HashSet<>();
Person p1 = new Person("张三",20);
Person p2 = new Person("李四",21);
Person p3 = new Person("王二",22);
//增加
hashSet.add(p1);
hashSet.add(p2);
hashSet.add(p3);
// hashSet.add(p3);这种方式添加是重复的
//这种是不会重复的,相当于内存中开辟了新的内存地址
//在重写equals(1)的方法后,依然可以添加,则代表hashcode值相等,如要不添加,需要从equals方法介入
hashSet.add(new Person("张三",20));
System.out.println(hashSet.size());
System.out.println(hashSet);
//删除
// hashSet.remove(p1);
//重写equals后,可以删除
hashSet.remove(new Person("张三",20));
// System.out.println(hashSet.size());
//遍历
//增强for
System.out.println("-----------------");
for (Object o: hashSet) {
System.out.println(o);
}
//迭代器
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断
System.out.println(hashSet.contains("p1"));
System.out.println(hashSet.isEmpty());
}
}
重写后的hashcode和equals方法【重点】
@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;
}
嫌麻烦可以直接使用IDE的自动重写方法(alt+insert)
当前版本的源码跟学习的课程不同
@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 && name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
存储结构:红黑树
在存入数据时,实现Comparable接口
TreeSet treeSet = new TreeSet<>();
Person p1 = new Person("zhangsan",20);
Person p2 = new Person("lisi",21);
Person p3 = new Person("wanger",22);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
//删除
// treeSet.remove(new Person("zhangsan",20));可以删除
System.out.println(p1);
//需要继承Comparable接口 并重写compareTo方法
public class Person implements Comparable{
//先比较姓名,后比较年龄
@Override
public int compareTo(Person o) {
//compareTo如果参数字符串等于此字符串,则返回值 0;
//如果此字符串小于字符串参数,则返回一个小于 0 的值;
//如果此字符串大于字符串参数,则返回一个大于 0 的值。
int n1 = this.getName().compareTo(o.getName());
int n2 = this.age-o.age;
//如果n1等于0,则代表名字相等,返回n2否则返回n1
return n1==0?n2:n1;
}
/**
* Treeset集合的使用
* Comparator:实现定制的比较
* Comparable:可比较的
*/
public class Demo06 {
public static void main(String[] args) {
//创建集合,并制定比较规则
TreeSet treeSet = new TreeSet<>(new Comparator() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getAge()- o2.getAge();
int n2 = o2.getName().compareTo(o2.getName());
return n2==0?n1:n2;
}
});
Person p1 = new Person("zhangsan",20);
Person p2 = new Person("lisi",21);
Person p3 = new Person("wanger",22);
treeSet.add(p1);
treeSet.add(p2);
treeSet.add(p3);
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
}
}
/**
* 使用TreeSet按照字符串长度进行比较
*/
public class Demo07 {
public static void main(String[] args) {
//创建集合,并制定比较规则
TreeSet treeSet = new TreeSet<>(new Comparator() {
@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("zhangsan");
treeSet.add("lisi");
treeSet.add("wangwu");
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
}
}
Map父接口
特点:存储一堆数据(Key-value),无序,无下标,键不可重复,值可重复。
方法
keySet是吧key的值遍历到一个集合中,所以Value需要再次遍历导致效率变低
Entry是直接把key和value变成一个个映射对,所以效率高
/**
* Map接口的使用
* 特点:
* (1)存储键值对
* (2)键不能重复,值可以重复
*/
public class Demo01 {
public static void main(String[] args) {
//创建集合
Map map = new HashMap<>();
//增加元素
map.put("cn","中国");
map.put("uk","英国");
map.put("ua","美国");
map.put("cn", "zhongguo"); // cn由于不能重复,value值就被覆盖了
System.out.println(map.size());
System.out.println(map.toString());
//删除元素
//map是根据键值进行删除的
// map.remove("uk");
System.out.println(map.size());
//遍历
//使用keySet只能先键值,需要value还需要map.get(key)
// Set keyset = map.keySet();
for (String key:map.keySet()) {
System.out.println(key+"----"+map.get(key));
}
//EntrySet()方法
// Set> entrySet = map.entrySet();
for (Map.Entry entry:map.entrySet()) {
System.out.println(entry.getKey()+entry.getValue());
}
//判断
System.out.println(map.containsKey("cn"));
System.out.println(map.containsValue("中国"));
System.out.println(map.isEmpty());
}
}
/**
* HashMap的使用
* 存储结构:哈希表(数组+链表+红黑树)
*
* 使用key可使hashcode和equals作为重复
*/
public class Demo02 {
public static void main(String[] args) {
//创建对象
HashMap hashMap = new HashMap<>();
Student s1 = new Student(10,"张三");
Student s2 = new Student(11,"李四");
Student s3 = new Student(12,"王五");
//增
hashMap.put(s1,"北京");
hashMap.put(s2,"上海");
hashMap.put(s3,"杭州");
// hashMap.put(s3,"南京");算重复元素
//在未重写hashcode和equals方法前,new是开辟堆中的新的空间,可以重复,重写后就不可以了
hashMap.put(new Student(10,"张三"),"北京");
System.out.println(hashMap.size());
System.out.println(hashMap.toString());
//删
// hashMap.remove(s1);
// System.out.println(hashMap.size());
//遍历
//keyset
System.out.println("------------------");
for (Student s:hashMap.keySet()){
System.out.println(s.toString()+hashMap.get(s));
}
//entry
for (Map.Entry entry: hashMap.entrySet()) {
System.out.println(entry.getKey()+entry.getValue());
}
//判断
System.out.println(hashMap.containsKey("s1"));
System.out.println(hashMap.containsValue("杭州"));
System.out.println(hashMap.isEmpty());
}
}
存储结构:
1、JDK1.8之前,采用的是哈希表(数组+链表)
2、JDK1.8之后,采用哈希表(数组+链表+红黑树)
源码分析总结:
1、HashMap刚创建时,table(哈希桶)为null,节省空间。当添加第一个元素时,容量调整为16
2、当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后的大小为原来的两倍,目的是减少调整元素的个数
3、JDK1.8 当每个链表长度大于8时,并且数组长度大于64, 会调整为红黑树,目的提高效率
4、JDK1.8 当链表长度小于6时,调整为链表
5、JDK1.8 以前,链表是头插入,之后是尾部插入
题外话:
HashSet的底层也是使用的HashMap
HashTable和Properties
HashTable(了解即可,已经弃用)
JDK1.0就存在,线程安全,运行效率低,不允许null作为key和value
Properties(可在IO框架最后一节有讲)
HashTable的子类,要求key和value都是String。通常用于配置文件的读取
TreeMap的使用
实现了SortedMap接口(是Map的子接口),可以对key进行自动排序
存储结构:红黑树
//treemap方法需要定制比较方法后,才能输出,否则会出现类型转换错误
// ClassCastException
public class Demo03 {
public static void main(String[] args) {
TreeMap treeMap = new TreeMap();
Student s1 = new Student(10,"张三");
Student s2 = new Student(11,"李四");
Student s3 = new Student(12,"王五");
treeMap.put(s1,"初一");
treeMap.put(s2,"初二");
treeMap.put(s3,"初三");
System.out.println(treeMap.size());
System.out.println(treeMap.toString());
}
}
//重写的方法
public class Student implements Comparable
@Override
public int compareTo(Student s) {
int n1 = this.age-s.getAge();
return n1;
}
补充:TreeSet和TreeMap的区别
实际上TreeSet的底层依然使用的是TreeMap
概念:集合工具类,定义了除了存取以外的集合常用方法
/**
* Colletion工具类的使用
*/
public class Demo04 {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(10);
list.add(12);
list.add(1);
list.add(31);
list.add(11);
list.add(41);
//sort排序
System.out.println(list.toString());
Collections.sort(list);
System.out.println(list.toString());
//binarySearcher二分查找
int n1 = Collections.binarySearch(list,31);
System.out.println(n1);
//copy复制
//这个方法在时,要求两个数组的长度一致,导致需要给新集合一个长度
List list2 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
list2.add(i);
}
Collections.copy(list2,list);
System.out.println(list2);
//reverse反转
Collections.reverse(list);
System.out.println(list);
//shuffle打乱
Collections.shuffle(list);
System.out.println(list);
//补充
//list集合转成数组,使用toArray方法
System.out.println("-----------");
Integer[] arr = list.toArray(new Integer[0]);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
//数组转成集合
String[] s = {"a","b","c"};
//asList转换后的集合是受限集合,无法增加和删除
List l = Arrays.asList(s);
System.out.println(l);
//基本类型数组转换成集合是,需要修改为包装类
Integer[] i = {1,2,3,4,5,6};
List l2 = Arrays.asList(i);
System.out.println(l2);
//错误写法,这样写导致数组又变成数组了
// int[] i = {1,2,3,4,5,6};
// List l2 = Arrays.asList(i);
// System.out.println(l2);
}
}