一、什么是集合
- 集合是Java中的第二个容器(就是在程序内存中用来存放数据的地方),Java的集合是一个可变长度大小的容器(集合就是可变长度的数组,集合的底层是数组)。
- 数组是用来存储相同数据类型的容器,集合是用来存放任意对象类型的数据的容器。
- 集合有长度,集合中的数据称为元素,集合分为很多种类。
二、Collection类型的集合
通过collection来了解集合的特点。
1、Collection
- Collection集合是单数据的集合,是根类集合。已知子类接口:set、list、vector
已知子类:Arraylist、hashset、treeset、linkedList - collection集合不能直接确定是有序集合还是无序集合,要根据具体的实例化方式来确定是有序的还是无序的。
1、1方法
以Arraylist为子类对象进行操作。 - ArrayList的默认初始容量为10;
- 存储的数据类型是基本数据类型的时候会进行自动装箱操作
package com.xingyun.collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* 根据collection接口来了解集合的基本使用
* @author langlang
*
* 2020年11月25日下午5:13:47
*/
public class CollectionClass {
public static void main(String[] args) {
//创建集合,使用多态的思想,不要忘记导包操作
Collection coll = new ArrayList();
//添加数据,同一个集合中可以存放任意对象类型的数据
coll.add(10);//源码进行了自动装箱
coll.add(20);
coll.add(true);
//查看数据元素的个数
System.out.println("元素个数"+coll.size());//元素个数3
}
}
- Collection集合,其实使用的是arraylist类的方法。
@Test
void test1() {
// 创建集合,使用多态的思想,不要忘记导包操作
Collection coll = new ArrayList();
// 添加数据,同一个集合中可以存放任意对象类型的数据
coll.add(10);// 源码进行了自动装箱
coll.add(20);
coll.add(true);
// 查看数据元素的个数
System.out.println("元素个数" + coll.size());// 元素个数3
// 指定查找,有该元素返回true,没有该元素返回false
System.out.println("指定查找" + coll.contains(10));// 指定查找true
/*
* 使用迭代器查找,Iterator根据集合创建迭代器,进行数据的遍历,注意普通迭代器来说 只能进行集合数据的查看和删除操作
* ListItertor属于list独有的
*/
Iterator iterator = coll.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.print(next);// 1020true
}
// 判断是空集合吗
System.out.println("集合是空的吗" + coll.isEmpty());// 集合是空的吗false
// 删除集合元素
System.out.println(coll.remove(10));// true
System.out.println("元素个数" + coll.size());// 元素个数2
}
- 在遍历集合的时候,可以使用Iterator迭代器和foreach循环(有顺序的集合可以使用普通for循环)
// 将集合转为数组
@Test
void test3() {
// 创建集合,使用多态的思想,不要忘记导包操作
Collection coll = new ArrayList();
coll.add(10);
coll.add(20);
coll.add(true);
Object[] array = coll.toArray();
for (Object object : array) {
System.out.println(object);
}
}
- 集合中的所有数据都可以是不同类型的,使用泛型<>可以约束集合中存放的数据类型。
/*
* 集合中存放的数据是任意对象类型的 如何约束集合中所存放的数据,使用泛型 使用泛型就可以指定集合中只能存放的数据类型是什么
* 使用泛型后,就不需要强转,迭代器就知道要什么类型
*/
@Test
void test4() {
// 创建集合,使用多态的思想,不要忘记导包操作
Collection<String> coll = new ArrayList<String>();
coll.add("好想爱这个世界啊");
coll.add("微光");
coll.add("疯人院");
// 使用泛型方便进行类型转换
for (String string : coll) {
System.out.println(string);
}
}
- 不能对正在使用的集合进行删除元素的操作
// 不能在遍历中对集合元素进行删除操作
/*
* 会产生并发异常,如下所示 ConcurrentModificationException
*/
@Test
void test2() {
// 创建集合,使用多态的思想,不要忘记导包操作
Collection coll = new ArrayList();
coll.add(10);
coll.add(20);
coll.add(true);
// 查询,集合的底层是数组,使用的是foreach
for (Object object : coll) {
System.out.println(object);
// 删除
coll.remove(10);
}
}
- 将集合可以转为数组使用
- 集合中可以存放复杂数据类型的操作
/*
* 集合中存放的数据是任意对象类型的 如何约束集合中所存放的数据,使用泛型 使用泛型就可以指定集合中只能存放的数据类型是什么
* 使用泛型后,就不需要强转,迭代器就知道要什么类型
*/
@Test
void test4() {
// 创建集合,使用多态的思想,不要忘记导包操作
Collection<String> coll = new ArrayList<String>();
coll.add("好想爱这个世界啊");
coll.add("微光");
coll.add("疯人院");
// 使用泛型方便进行类型转换
for (String string : coll) {
System.out.println(string);
}
}
/*
* 集合中存储复杂数据类型的操作 对象类型 自定义对象 数组类型 元素是数组 集合类型 元素是集合
*/
@Test
void test5() {
// 创建集合,使用多态的思想,不要忘记导包操作
Collection<Student> stus = new ArrayList<Student>();
stus.add(new Student(10, "zs"));
stus.add(new Student(20, "ww"));
stus.add(new Student(19, "ls"));
// 遍历
for (Student student : stus) {
System.out.println(student);
}
}
// 数组类型的集合
@Test
void test6() {
Collection<Student[]> stus = new ArrayList<Student[]>();
stus.add(new Student[] { new Student(10, "zs"), new Student(20, "zs"), new Student(30, "zs") });
Iterator<Student[]> iterator = stus.iterator();
while (iterator.hasNext()) {
Student[] next = iterator.next();
for (Student student : next) {
System.out.println(student);
}
}
}
2、List
- List集合为有序可以重复的集合,元素是有顺序的,并且元素可以重复
- 三个子类的对比
ArrayList:列表集合,线程不安全,查询速度块,更新速度慢
LinkedList:链表集合,线程不安全,查询速度慢,更新速度相对较快
Vector:列表集合,线程安全,查询速度块,更新速度慢,使用的enum做迭代器进行操作 - 列表和链表的区别
列表:有顺序,每一个元素都对应一个下标记
链表:在内存中给每一个元素设置一个尾节点,首尾对象连接。
2、1ArrayList 默认初始容量大小为10
- ArrayList,他的底层是数组,集合中的数据都存放在集合的object数组中;Object [ ] elementData;因此数据在集合中是有顺序的,元素可以重复,每一个元素都对应于一个下标。
@Test
void list01(){
//实例化,泛型不能是基本类型
List<Integer> ls = new ArrayList<Integer>();
//添加数据,下标0---size-1
ls.add(100);
ls.add(200);
ls.add(200);
System.out.println(ls.size());//3
//给指定位置新增,对原数组中的元素进行位置调整,将新元素插入到该数组
ls.add(3, 300);
//使用的是AbstractCollection的toString方法
System.out.println(ls);//[100, 200, 200, 300]
System.out.println(ls.size());//4
//修改,修改哪一个元素,修改为什么
ls.set(3, 200);
System.out.println(ls);//[100, 200, 200, 200]
//查询 get
System.out.println(ls.contains(100));//true
Integer integer = ls.get(0);
System.out.println(integer);//100
}
- 遍历集合
//使用迭代器进行集合操作
@Test
void list02(){
List<Integer> ls = new ArrayList<Integer>();
ls.add(100);
ls.add(200);
ls.add(300);
// /*
// * 删除元素这块有一个混淆点
// */
// ls.remove(100);//这样表示删除的是100位置的元素
// ls.remove(new Integer(100));//这样表示删除的是100这个元素
//遍历集合
//增强性for循环
for (Integer integer : ls) {
System.out.println(integer);
}
System.out.println("--------");
//使用普通的迭代器,只能对集合进行删除操作
Iterator<Integer> iterator = ls.iterator();
int index = 0;
//判断有没有下一个元素,指针不动,指针起始位置是第一个元素之前
while(iterator.hasNext()) {
//指针移动到有效元素位置上去
Integer next = iterator.next();
index++;
System.out.println(next);
if(index==1) {
iterator.remove();
}
}
System.out.println("--------");
//使用list独有的迭代器
ListIterator<Integer> listIterator = ls.listIterator();
while(listIterator.hasNext()) {
Integer next = listIterator.next();
System.out.println(next);
listIterator.set(400);//这样将会把所有的值都设置为400
//依然不可以使用添加功能
}
System.out.println("--------");
//使用普通的for循环
for (int i = 0; i < ls.size(); i++) {
System.out.println(ls.get(i));
}
}
结果如下:
2、2LinkedList
- LinkedList用来做快速更新集合数据
方法如下: - addFirst( E o );
- addLast( E o );
- getFirst( );
- getLast( );
- peek( );
- poll( );
- remove ( );
- removeFirst( );
- removeLast( );
- element( );
代码演示如下:
@Test
void link() {
//面向接口编程
List<String> ll = new LinkedList<String>();
LinkedList<String> lls = new LinkedList<String>();
//每一次都在末尾新增
ll.add("100");
ll.add("200");
ll.add("300");
ll.add(1,"400");
System.out.println(ll);//[100, 400, 200, 300]
lls.add("zs");
lls.add("ls");
lls.add("ww");
System.out.println(lls);//[zs, ls, ww]
//查看
System.out.println(ll.get(0));
System.out.println(lls.get(0));
System.out.println("第一个元素"+lls.getFirst());//第一个元素zs
System.out.println("最后一个元素"+lls.getLast());//最后一个元素ww
//遍历集合
for (String string : lls) {
System.out.println(string);
}
System.out.println("--------");
//使用迭代器进行遍历
Iterator<String> iterator = lls.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
2、3Vector 数组
1、介绍
- Vector,可变长度的数组,默认初始容量大小是10
- 可以手动进行设置初始容量的大小。
- 在自定义的时候,要选取合适的扩容方式
- new Vector(2);默认扩容机制是之前容量的2倍扩容
- new Vector(2,20);参数一是设置的初始容量,参数二是扩容机制。
2、方法
- addElement(E obj);
- capacity( );
- copyInto(Object [] anArray);
- elements( );
代码演示如下:
//Vector的扩容机制
@Test
void vt01() {
//实例化Vector,扩容因子1(扩容的时机),扩容机制为2倍
//初始容量为2
Vector<Integer> nums = new Vector<Integer>(2);
System.out.println("容量大小"+nums.capacity());//容量大小2
nums.add(100);
nums.add(200);
nums.add(300);
nums.add(400);
System.out.println(nums.size());//4
//当内容的长度变成和容量的大小一样长时,便进行扩容,扩大为原来的2倍
System.out.println("容量大小"+nums.capacity());//容量大小4
}
//集合的遍历
@Test
void vt02() {
//实例化集合
Vector<Integer> nums = new Vector<Integer>();
nums.add(100);
nums.add(200);
nums.add(300);
//遍历
//使用增强性的for循环对集合进行遍历
for (Integer integer : nums) {
System.out.println(integer);
}
System.out.println("----------");
//使用迭代器对集合进行遍历
Iterator<Integer> iterator = nums.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("----------");
//使用Vector自己的,获取所有的元素保存到Enumeration集合中
Enumeration<Integer> elements = nums.elements();
while(elements.hasMoreElements()) {
Integer nextElement = elements.nextElement();
System.out.println(nextElement);
}
}
3、Set集合,无序不可重复的集合
3、1TreeSet
3、1、1.介绍
- 此类实现Set接口,该接口由TreeMap实例支持。此类保证排序后的set按照升序排列元素,根据使用的构造方法不同,可能会按照元素的自然顺序进行排序,或者按照在创建set时所提供的比较器进行排序。
- Treeset是set的已知实现子类,默认按照自然排序。
- 该集合存和取的顺序不一样
- 底层存储数据的时候,是按照排序方式进行存储的
数字:按大小顺序进行存储
字母:按字母顺序进行存储
汉字:按hashcode值进行存储 - 我们也可以使用自定义的比较器:根据自定义比较器的返回值决定元素是否进行交换。
代码演示如下:
/**
* 自然顺序
* 数字:按照数字的大小
* 汉字:按照hashcode的值
* 英语:26个字母
*/
@Test
void set01() {
//实例化
Set<Integer> snum = new TreeSet<Integer>();
//存数据的时候要先进行判断原集合中有没有该元素,
/*
* add方法的返回值是一个boolean类型的,
* 如果集合中不存在我们要存入的元素,则会存储成功
* 如果存储成功则返回true,否则返回false
*/
snum.add(10);
snum.add(20);
System.out.println(snum.add(30));//true
System.out.println(snum.add(30));//false
System.out.println("------------");
//遍历集合
//使用增强型for循环进行遍历
for (Integer integer : snum) {
System.out.println(integer);
}
System.out.println("------------");
//使用迭代器进行遍历
Iterator<Integer> iterator = snum.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("------------");
//该方法是1.8之后才有的
Spliterator<Integer> spliterator = snum.spliterator();
System.out.println(spliterator.characteristics());
}
@Test
void set02() {
//实例化
Set<String> snum = new TreeSet<String>();
//存数据的时候他会先进行判断
snum.add("a");
snum.add("b");
snum.add("c");
snum.add("d");
String a = "啊";
String a1 = "和";
String a2 = "打";
System.out.println(a.hashCode());//21834
System.out.println(a1.hashCode());//21644
System.out.println(a2.hashCode());//25171
snum.add(a);
snum.add(a1);
snum.add(a2);
System.out.println(snum);//[a, b, c, d, 和, 啊, 打]
}
//自定义排序规则
@Test
void set03() {
//实例化,传入比较器
Set<Integer> snum = new TreeSet<Integer>(new MyComparator());
snum.add(10);
snum.add(20);
snum.add(15);
snum.add(30);
System.out.println(snum);//[30, 20, 15, 10]
}
package com.xingyun.set;
import java.util.Comparator;
/**
* 自定义的逆序排列比较器
* @author langlang
*
* 2020年11月26日下午3:11:30
*/
public class MyComparator implements Comparator<Integer>{
//逆序排列
@Override
public int compare(Integer num1, Integer num2) {
//返回值,决定两个元素是否交换
if(num1>num2) {
return -1;//-1代表不交换
}else if(num1<num2) {
return 1;//1代表交换
}else {
return 0;
}}
}
3、1、2注意事项:
TreeSet存储对象类型的时候,因为他是自然排序,对于对象来说,不能够直接进行比较,否则会抛出ClassCastException异常。处理方式见代码。
//使用Treeset保存学生对象
@Test
void colls4() {
TreeSet<Student> stus = new TreeSet<Student>(new MyComparator());
/*
* 不能直接比较,默认的是自然排序
*/
//方式一
/*
* 自定义比较器来进行比较,
*/
stus.add(new Student(30));
stus.add(new Student(20));
stus.add(new Student(15));
stus.add(new Student(50));
stus.add(new Student(18));
System.out.println(stus);
}
}
class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// 两个对象去比较,实际是按照学生的年龄进行比较
if (o1.age > o2.age) {
return 1;// 1代表交换顺序
} else if (o1.age < o2.age) {
return -1;
} else {
return 0;
}
}
3、2HashSet
3、1介绍
- Hashset的底层是hashmap,根据hash码进行排序。可以存放null值,null只能有一个
- HashSet的默认初始容量是16。
3、2方法
构造方法:
由构造方法可得:HashSet的初始容量大小为16,加载因子为0.75;
方法:
4、Collections
4、1介绍
- Collections是collection类型集合的操作类
4、2方法 - addAll(Collection<? super T> c, T… a)
- unmodifiableSet(Set<? extends T> s);
获得一个不可变的集合; - replaceAll(List list, T oldVal, T newVal) ;
- reverse(List<?> list);
- sort(List list) ;
- sort(List list, Comparator<? super T> c) ;
- 通过不安全集合,得到一个线程安全的集合
synchronizedCollection(Collection c); - 获取集合中的最大值和最小值(比较器)
max(Collection<? extends T> coll);
min(Collection<? extends T> coll);
4、3方法的代码演示如下:
package com.xingyun.collections;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import org.junit.jupiter.api.Test;
/**
* Collections集合的操作
*
* @author langlang
*
* 2020年11月28日下午3:10:16
*/
class CollectionsClass {
@Test
void colls1() {
// 如何快速得到一个固定大小的集合
List<Integer> list = Arrays.asList(10, 20, 30);
list.set(1, 100);
System.out.println(list);//[10, 100, 30]
// 通过集合得到一个不可变的集合
Collection<Integer> coll = Collections.unmodifiableCollection(list);
// coll.add(100);//这样子会报错,因为他已经是一个不可变的集合了,不能对他再进行增加操作
System.out.println(coll);//[10, 100, 30]
// 给指定的集合添加元素
ArrayList<Integer> nums = new ArrayList<Integer>();
Collections.addAll(nums, 100, 200, 300);
System.out.println(nums);//[100, 200, 300]
// 替换
boolean replaceAll = Collections.replaceAll(nums, 100, 1000);
System.out.println("是否替换成功" + replaceAll);//是否替换成功true
System.out.println("替换后的集合" + nums);//替换后的集合[1000, 200, 300]
}
// 使用集合进行排序
@Test
void colls2() {
// list集合,元素的student对象
ArrayList<Student> stus = new ArrayList<Student>();
stus.add(new Student(30));
stus.add(new Student(20));
stus.add(new Student(15));
stus.add(new Student(50));
stus.add(new Student(18));
// 进行排序
// // 方式一
// Collections.sort(stus, new MyComparator());
// for (Student student : stus) {
// System.out.println(student);
// }
// 方式二 对集合中的对象,实现comparable接口并重写compare To
Collections.sort(stus);
for (Student student : stus) {
System.out.println(student);
}
}
@Test
void colls3() {
//其他方法
ArrayList<Integer> nums = new ArrayList<Integer>();
Collections.addAll(nums, 100,200,300);
ArrayList<Integer> nums01 = new ArrayList<Integer>();
Collections.addAll(nums01, 100,200,300);
//交换 swap(List<?> list, int i, int j)
Collections.swap(nums, 0, 2);
System.out.println(nums);//[300, 200, 100]
//set方法会返回北替换的值
System.out.println(nums.set(0, 500));//300
System.out.println(nums);//[500, 200, 100]
//比较 如果两个指定 collection 中没有相同的元素,则返回 true。
boolean disjoint = Collections.disjoint(nums, nums01);
System.out.println(disjoint);//false
}
}
class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// 两个对象去比较,实际是按照学生的年龄进行比较
if (o1.age > o2.age) {
return 1;// 1代表交换顺序
} else if (o1.age < o2.age) {
return -1;
} else {
return 0;
}
}
}
class Student implements Comparable<Student> {
int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int age) {
super();
this.age = age;
}
@Override
public String toString() {
return "Student [age=" + age + "]";
}
@Override
public int compareTo(Student stu) {
// 两个对象去比较,实际是按照学生的年龄进行比较
if (this.age > stu.age) {
return 1;// 1代表交换顺序
} else if (this.age < stu.age) {
return -1;
} else {
return 0;
}
}
}
三、Map集合
Map类型的集合称为键值对集合;
a.HashMap:线程不安全,按照hash码的值进行排序并允许使用null值和null键,HashMap的执行速度高于TreeMap
b.TreeMap:键不可以为null,值可以为null,根据键的值使用自然排序的方式升序排序,可以使用Comparator进行手动设置排序方式。
c.HashTable:线程安全的,键和值都不能为null.
1、HashMap(hashset)
1.1介绍
- 允许使用null值和null键
- HashMap,初始容量为16,加载因子0.75,扩容倍数是两倍
1、2方法 - put(K key, V value);
- remove(Object key);
package com.xingyun.map;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.jupiter.api.Test;
/**
* HashMap键值对集合
* @author langlang
*
* 2020年11月28日下午4:33:46
*/
public class HashMapClass {
@Test
void test01(){
//实例化map集合
HashMap<String,Integer> stus = new HashMap<String,Integer>();
//键不能重复,可以为null
//值可以重复,可以为null
stus.put("001",100);
stus.put("002",200);
//put方法也可以叫做更新方法
/*
* 如果该键已经存在,那么便更新该键
* 如果该键不存在,便添加该键
*/
// stus.put("001",300);
stus.put(null,null);
stus.put("003",300);
// System.out.println("删除前"+stus);
// //删除
// Integer remove = stus.remove("001");
// //该值返回的是删除的元素的值
// System.out.println(remove);
//查询 遍历key 遍历value 整体遍历
//将map集合中的所有的value值保存到一个collection集合中
Collection<Integer> values = stus.values();
for (Integer integer : values) {
System.out.println("值为"+integer);
}
//遍历所有的key
Set<String> keySet = stus.keySet();
for (String string : keySet) {
System.out.println("键为"+string);
}
//使用enteySet对集合进行遍历,将map集合的键值对关系保存为entry存放到set集合中
Set<Entry<String, Integer>> entrySet = stus.entrySet();
for (Entry<String, Integer> entry : entrySet) {
System.out.println("键是"+entry.getKey()+",值是"+entry.getValue());
}
//判断
System.out.println(stus.equals(200));
//集合的长度
//集合的长度指的是键值对的个数
System.out.println("集合的长度是"+stus.size());
//映射
//如果此映射包含对于指定的键的映射关系,则返回 true。
System.out.println(stus.containsKey("001"));//true
System.out.println(stus.containsKey("004"));//false
System.out.println(stus.containsValue(null));//true
}
//HashMap存储对象类型
@Test
void test02(){
//实例化Map集合
HashMap<String,Student> stus = new HashMap<String,Student>();
//要注意null对象
stus.put("2101", new Student("zs"));
stus.put("2102", new Student("zs01"));
stus.put("2103", new Student("zs02"));
stus.put("2103", new Student(null));
System.out.println(stus);
//因为HashMap中允许有null值和null键,因此我们要注意null值的获取
Collection<Student> values = stus.values();
for (Student student : values) {
//注意这里要做非空判断
if(student!=null) {
System.out.println(student.name);
}
}
}
}
class Student{
String name;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name) {
super();
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
}
2、Hashtable
2、1介绍
- Hashtable的初始默认容量是11,加载因子0.75,扩容机制2倍加1
- 键和值都不能为null,键和值可以是任意对象类型(自定义对象)
- 为了成功的在哈希表中存储和检索对象,用做键的对象必须实现hashCode方法和equals方法
2、2方法
构造方法
方法使用以及底层容量获取(反射机制)
package com.xingyun.map;
import java.lang.reflect.Field;
import java.util.Hashtable;
import java.util.Map.Entry;
import org.junit.jupiter.api.Test;
/**
* Hashtable
* @author langlang
*
* 2020年12月1日下午6:59:11
*/
public class HashtableClass {
//hashtable键是基本类型(封装类)
@Test
void hashtable01() {
//实例化,默认的加载因子是0.75
//我们设置初始容量为10
Hashtable<Integer,String> nums = new Hashtable<Integer,String>(10);
//循环保存数据
for (int i = 0; i < 20; i++) {
nums.put(i,i+"");
}
/*首先扩容第一次:10*2+1=21;21*0.75<20,因此继续扩容
* 再扩容第二次:21*2+1=43;43*0.75>20,因此容量为43
*/
//打印数据
System.out.println(nums);
getCp(nums);//集合的容量43
}
//键是对象类型
//如果hashtable的键是对象,该对象重写实现hashCode方法和equals方法
@Test
void hashtable02() {
Hashtable<Person,String> persons = new Hashtable<Person,String>();
//如果重写hashcode方法,会导致对象为同一个,key重复了
persons.put(new Person(20), "中国人");
persons.put(new Person(20), "外国人");
/*
* 这样键为同一个,put方法的第二个会将第一个的结果进行覆盖
*/
System.out.println(persons);//{com.xingyun.map.Person@62d=外国人}
System.out.println("大小是"+persons.size());
System.out.println(persons.toString());
//注意:不可以存放null值,会报空指针异常
// persons.put(null, null);
}
public void getCp(Hashtable<Integer,String> map) {
Class c = map.getClass();
try {
Field declaredField = c.getDeclaredField("table");
//获取权限
declaredField.setAccessible(true);
Entry[] entry = (Entry[])declaredField.get(map);
System.out.println("集合的容量"+entry.length);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Person{
String name;
int age;
public Person(String name) {
super();
this.name = name;
}
public Person(int age) {
super();
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
3、TreeMap(treeset) 自然排序
3、1介绍
- TreeMap是根据键进行自然排序排序的键值对集合,可以使用自定义比较器来改变比较规则
- TreeMap键不可以为null,值可以是null
package com.xingyun.map;
import java.util.Comparator;
import java.util.TreeMap;
import org.junit.jupiter.api.Test;
/**
* TreeMap集合
* 自然排序集合
* @author langlang
*
* 2020年12月1日下午8:03:51
*/
public class TreeMapClass {
/*
* comparable是一个函数式接口
*/
@Test
void treemap01() {
//key可以为null,value不能为null
TreeMap<Integer,String> nums = new TreeMap<Integer,String>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if(o1 > o2) {
return -1;
}else if(o1 < o2) {
return 1;
}else {
return 0;
}
}
}
);
nums.put(10, "aa");
nums.put(5, "aa");
nums.put(3, "aa");
nums.put(15, "aa");
System.out.println(nums);//{15=aa, 10=aa, 5=aa, 3=aa}
}
@Test
void treemap02() {
//使用自定义的比较器
TreeMap<Integer,String> nums = new TreeMap<Integer,String>(new ascMyComparator());
nums.put(10, "aa");
nums.put(5, "aa");
nums.put(3, "aa");
nums.put(15, "aa");
nums.put(18, "aa");
System.out.println(nums);//{18=aa, 15=aa, 10=aa, 5=aa, 3=aa}
}
}
//自定义的正序比较器
class ascMyComparator implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
if(o1>o2) {
return -1;//1代表交换
}else if(o1<o2) {
return 1;
}else {
return 0;
}
}
}
四、其他集合。
1、Queue
队列集合,先进先出。FIIFO。Queue队列集合使用的是LinkedList操作。
方法如下:
代码演示如下:
@Test
void queue(){
Queue<String> strs = new LinkedList<String>();
strs.add("aaa");
strs.add("bbb");
strs.add("ccc");
strs.add("ddd");
System.out.println(strs);
//使用for循环进行遍历
for (String string : strs) {
System.out.println(string);
}
System.out.println("--------");
//queue自己的方法
//查找第一个元素
System.out.println(strs.peek());//aaa
//移除第一个元素,并得到第一个元素
System.out.println(strs.poll());//aaa
System.out.println(strs);//[bbb, ccc, ddd]
//得到第一个元素
System.out.println(strs.element());//bbb
System.out.println(strs);//[bbb, ccc, ddd]
}
2、Properties
2、1介绍
- Properties是键值对集合,该集合可以使用io流的操作与properties类型的文件进行数据交互
- properties文件就是指以properties后缀结尾的文件
- 该文件中的数据全是字符串的,并且是键值对形式的
- 该文件在日常的使用中大多数用来保存账号密码,保存的是不重复的数据信息
- 在eclipse中可以直接创建properties文件,该文件必须保存到项目的根目录下(此时不允许将文件保存到src下,src是资源文件夹)
2、1方法及代码演示如下
// 将外部文件的内容保存到properties对象中
@Test
void properties01() {
// 实例化properties对象
Properties pt = new Properties();
// //存储数据
// pt.put("aa", 100);//hashtable的方法,不要使用
// pt.setProperty("bb","200");
// pt.setProperty("bb01","300");
// pt.setProperty("bb02","400");
// System.out.println(pt);//{bb02=400, aa=100, bb01=300, bb=200}
// //通过键来获取值
// System.out.println(pt.get("bb"));//200
// 记载,外部文件,将外部文件的内容保存到properties对象中,使用load方法
// 参数是InputStream字节输入流
FileInputStream inputstream;
try {
inputstream = new FileInputStream(new File("user.properties"));
// 读取文件内容
pt.load(inputstream);
System.out.println(pt);// {password=123456, username=zs}
// 修改数据,此时修改的是properties内存中的数据
pt.setProperty("username", "zhangsan");
System.out.println(pt);// {password=123456, username=zhangsan}
// 将内存中对象中的数据,持久化保存到properties文件中
FileOutputStream outputstrem = new FileOutputStream(new File("user.properties"));
// 第二个参数就是起一个注释的作用
pt.store(outputstrem, "修改后的账号信息");
System.out.println("数据持久化成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 读取数据
@Test
void properties02() {
Properties pt = new Properties();
FileInputStream inputstream;
try {
inputstream = new FileInputStream(new File("user.properties"));
pt.load(inputstream);
System.out.println(pt);// {password=123456, username=zhangsan}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 读取数据
@Test
void properties03(){
Properties pt = new Properties();
pt.setProperty("name","lisi");
pt.setProperty("pass", "11111");
//将内存中对象中的数据持久化保存到properties文件中
try {
FileOutputStream outputstrem = new FileOutputStream(new File("user.properties"));
pt.store(outputstrem, "修改后的账号信息");
System.out.println("数据持久化保存成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}