1.集合的概述
1.1相关概念
- 集合、数组都是对多个数据进行存储操作的结构,简称java容器(说明:此时的存储,主要是指内存方面的存储,不涉及持久化的存储比如数据库、txt文件)
- 数组在存储多个数据结构方面的优点
- 一旦初始化后,长度就确定了
- 数组一旦定义好,其元素的类型也就确定了,我们只能操作指定类型的数据
- 数组的存在多个数据结构方面的缺点
- 一旦初始化后,其长度不可修改
- 数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高
- 获取数组中实际元素个数的需求,数组没有现成的属性和方法可用
- 数组存在数据的特点:有序、可重复。对于无序、不可重复的需求不能满足
1.2Java集合的分类
Java集合可以分成Collection和Map两种体系
- Collection接口:单列数据,定义了一组存储数据方法的集合
- List:元素有序、可重复的集合(LLinkedList、ArrayList,Vector)
- Set:元素无序,不可重复的集合(HashSet、LinkHashSet、TreeSet)
- Map接口
- 双列数据,保存具有映射关系"key-value对"集合(HashMap、LinkedHaspMap、TreeMap、HashTable、Properties)
2.Collection
2.1接口方法
- 添加
add(Object obj)
addAll(Collection coll) - 获取有效元素的个数
int size() - 清空集合
void clear() - 是否是空集合 boolean isEmpty()
- 是否包含某个元素
boolean contains(Object obj):是通过元素的equals方法来判断是否是同一个对象
boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。 - 删除
boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
boolean removeAll(Collection coll):取当前集合的差集 - 取两个集合的交集
boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c - 集合是否相等
boolean equals(Object obj) - 转成对象数组
Object[] toArray() - 获取集合对象的哈希值
hashCode() - 遍历
iterator():返回迭代器对象,用于集合遍历
举例
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add("11");//添加元素
collection.add("22");
collection.add("33");
System.out.println(collection.size());//获取有效元素的个数
System.out.println(collection.isEmpty());//是否为空
System.out.println(collection.contains("11"));//是否包含某个元素
collection.remove("11");//:通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
System.out.println("==========================");
for(Object o:collection)
{
System.out.println(o);
}
String s = collection.toString();
System.out.println(s);
Object[] objects = collection.toArray();//转化为数组
System.out.println("==================================");
for(Object o:objects)
{
System.out.println(o);
}
System.out.println("========================");
ArrayList<Object> objects1 = new ArrayList<>();
objects1.add("22");
collection.removeAll(objects1);//当前集合的差集
for(Object o:collection)
{
System.out.println(o);
}
collection.add("22");
System.out.println("=====================");
boolean b = collection.retainAll(objects1);//获取两个集合的交集
// System.out.println(b);
for(Object o:collection)
{
System.out.println(o);
}
System.out.println(collection.equals(objects1));//判断两个集合是否相等
}
3.Iterator迭代器接口
3.1使用 Iterator 接口遍历集合元素
- Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
- GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。类似于“公交车上的售票员”、“火车上的乘务员”、“空姐”。
- Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
- Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
- 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
3.2Iterator接口的方法
- 使用next()获得序列中的下一个元素。
- 使用hasNext()检查序列中是否还有元素。
- 使用remove()将迭代器新返回的元素删除。
public static void main(String[] args) {
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
Iterator<Object> iterator = arrayList.iterator();
//遍历方式一
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println("================================");
iterator= arrayList.iterator();
//遍历方式二
for(int i=0;i<arrayList.size();i++)
{
System.out.println(iterator.next());
}
iterator=arrayList.iterator();
System.out.println("================================");
//遍历方式三
while (iterator.hasNext())//判断是否有下一个元素
{
//next():①指针下移 ②将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
}
remove的使用
@Test
public void tes1(){
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
Iterator<Object> iterator = arrayList.iterator();
while(iterator.hasNext())
{
int next = (int)iterator.next();
if(next==1)
{
iterator.remove();
}
}
iterator=arrayList.iterator();
while(iterator.hasNext())
{
System.out.println(iterator.next());
}
}
注意:
- Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方 法,不是集合对象的remove方法。
- 如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。
3.3使用 foreach 循环遍历集合元素
- Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
- 遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
- 遍历集合的底层调用Iterator完成操作。
- foreach还可以用来遍历数组。
- 修改遍历结果不会改变原来的值
//for(集合元素的类型 局部变量:集合对象) 内部仍调用迭代器
@Test
public void text2()
{
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
for(Object x:arrayList)
{
System.out.println(x);
}
}
4.List接口
4.1List接口的概述
- collocation接口:单列集合用来存储一个个对象
- List接口:存储有序的可重复的数据,动态数组,代替原有的数组
- list接口有:ArrayList,LinkedList和vector
4.2ArrayList,LinkedList和vectors三者的异同
同:三个都实现了List接口,存储数据的特点相同:存储有序可重复的数据
不同:
- ArrayList作为List的主要实现类,线程不安全,效率高。底层使用Object[] elementData存储
- LinkedList:对应频繁的插入和删除操作,效率都比ArrayList高,底层使用双向链表存储
- vector:作为List接口的古老实现类,线程安全、效率低、底层使用Object[] elementData存储
4.3ArrayList源码分析
- jdk7以下
底层创建一个长度为10的Object[] elementData数组,使用add向数组中添加元素,如果添加元素导致底层Object[] elementData数组容量不够,则扩容,默认情况下扩容到原来的1.5倍,同时将数据原有的数据赋值到新数组中,建议开发中使用带参的构造器 ArrayList lsit=new ArrayList(int capacity) - jdk8中ArrrayList的变化
底层Object[] elementData数组初始化为{}并没有创建长度第一次调用add()时,底层才创建了长度为10的数组,并将数据添加到elementData中,后面的添加和扩容操作与jdk7 无异
小结:jdk7中ArrayList对象的创建类似于单例模式的饿汉式模式,而jdk8中ArrayList对象的创建类似于单例模式的懒汉式模式,延迟数组的创建,节省内存
4.4LinkList
采用链表的形式来存储数据
4.5List接口常用方法
方法名 | 说明 |
---|---|
void add(int index, Object ele) | 在index位置插入ele元素 |
boolean addAll(int index, Collection eles) | 从index位置开始将eles中的所有元素添加进来 |
Object get(int index) | 获取指定index位置的元素 |
int indexOf(Object obj) | 返回obj在集合中首次出现的位置 |
int lastIndexOf(Object obj) | 返回obj在当前集合中末次出现的位置 |
Object remove(int index) | 移除指定index位置的元素,并返回此元素 |
Object set(int index, Object ele) | 设置指定index位置的元素为ele |
List subList(int fromIndex, int toIndex) | 返回从fromIndex到toIndex位置的子集合 |
@Test
public void test3()
{
ArrayList<Object> list = new ArrayList<>();
list.add(1);//增
list.add(2);
list.add(3);
//差
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i));
}
list.remove(2);//通过下标删除
System.out.println("=====================");
for(Object o:list)
{
System.out.println(o);
}
list.set(0,10);//改
System.out.println("======================");
for(Object o:list)
{
System.out.println(o);
}
list.remove(new Integer(10));//通过值删除
System.out.println("=======================");
for(Object o:list)
{
System.out.println(o);
}
}
LinkList新增方法
void addFirst(Object obj)
void addLast(Object obj)
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()
4.6vector
在创建对象时,底层都创建了长度为10的数组,扩容时,扩大到原来的2倍
5 set接口
5.1set接口的概述
- set接口:存储无序,不可重复的数据
以Hashset为例说明:
- 无序性:不等于随机性,存储的数据在底层数组中并非按照数组的索引的顺序添加,而是根据数据的哈希值
- 不可重复性:保证添加的元素按照equals()判断时,不能返回true,即:相同的元素。只能添加一个
- Hashset:作为set接口的主要实现类,线程不安全,可以存储null值
- LinkedHashSet:作为HashSet子类,遍历其内部数据时,可以按照添加顺序遍历
- TreeSet:可以按照添加对象属性进行排序,采用了红黑树的方式进行存储
- HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
- 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”
5.1.1向HashSet中添加元素的过程
HashSet特点
- HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
- HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
- HashSet 具有以下特点:
- 不能保证元素的排列顺序
- HashSet 不是线程安全的
- 集合元素可以是 null
- 4.HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
当向 HashSet 集合中存入一个元素a时,HashSet 会调用该对象的 hashCode() 方法来得到该对象a的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象在 HashSet 底层数组中的存储位置。(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布,该散列函数设计的越好)
如果两个元素a,b的hashCode()值相等,会再继续调用equals方法,如果equals方法结果为true,添加失败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。
如果两个元素a,b的hashcode()不相等,添加成功
jdk7:元素a放在数组中,指向原来的元素
jdk8:原来的元素在数组中,指向元素a
总结:7上8下
Hashset底层:数组+链表(数组初始容量为16,当如果使用率超过0.75,就会扩大容量为原来的2倍。
如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
5.1.2重写 hashCode() 方法的基本原则
- 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。
- 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。
- 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。
5.2LinkedHashSet的使用
LinkedHashSet作为HashSet子类, 在添加数据的同时,每个数据还维护了两个引用,记录此数据的前一个数据和后一个数据
优点:对于频繁的遍历操作,LinkedHashSet更方便
@Test
public void test4()
{
HashSet<Object> hashSet = new LinkedHashSet<>();
hashSet.add(1);
hashSet.add(3);
hashSet.add(1);
hashSet.add("hollow word");
hashSet.add("hi");
for(Object o:hashSet)
{
System.out.println(o);
}
}
5.3TreeSet
- 向TreeSet中添加的数据,要求是相同类的对象
- 两种排序方式:自然排序和定制排序(comparator)
- 在自然排序中,比较两个对象是否相等的标准为compareTo返回0而不是equals
自然排序
public class People implements Comparable{
private String name;
private int age;
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
People people = (People) o;
return age == people.age && Objects.equals(name, people.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public People(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 int compareTo(Object o) {
if(o instanceof People)
{
People o1 = (People) o;
if(this.getAge()!=o1.getAge())
{
return this.getAge()<o1.getAge()?1:-1;
}
else
{
return this.getName().compareTo(o1.getName());
}
}
return 0;
}
}
@Test
public void test5(){
TreeSet<People> treeSet = new TreeSet<>();
treeSet.add(new People("zhangsan",19));
treeSet.add(new People("zhangsan",90));
treeSet.add(new People("lisi",23));
treeSet.add(new People("wangqiang",44));
treeSet.add(new People("aa",35));
Iterator<People> iterator = treeSet.iterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
定制排序
@Test
public void text6()
{
Comparator comparator = new Comparator(){
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof People && o2 instanceof People) {
People p1=(People) o1;
People p2=(People) o2;
if(p1.getAge()!=p2.getAge())
{
return p1.getAge()>p2.getAge()?1:-1;
}
else
return p1.getName().compareTo(p2.getName());
}
return 0;
}
};
TreeSet treeSet = new TreeSet<>(comparator);
treeSet.add(new People("zhangsan",19));
treeSet.add(new People("zhangsan",90));
treeSet.add(new People("lisi",23));
treeSet.add(new People("wangqiang",44));
treeSet.add(new People("aa",35));
Iterator iterator = treeSet.iterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
经典例题
public class Person {
private int id;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
}
@Test
public void test7()
{
HashSet set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");
set.add(p1);
set.add(p2);
System.out.println(set);
p1.setName("CC");
set.remove(p1);
System.out.println(set);
System.out.println("=================");
set.add(new Person(1001,"CC"));
System.out.println(set);
System.out.println("================");
set.add(new Person(1001,"AA"));
System.out.println(set);
}
6. Map接口
6.1Map接口的概述
- Map与Collection并列存在。用于保存具有映射关系的数据:key-value
- Map 中的 key 和 value 都可以是任何引用类型的数据
- Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法
- 常用String类作为Map的“键”
- key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value
- Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类
6.1 Map实现类结构
- Map:双列数据,存储key-value对的数据,类似于高中的函数
- HashMap:作为Map的主要实现类,线程不安全,效率高,可以存储null的key和value
- LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现(在原因的hashMap底层结果基础上,添加一对指针,指向前一个和后一个元素,对于频繁的遍历操作,此执行效率高于HashMap)
- TreeMap: 保证按照添加的key-value;对进行排序,实现排序遍历,此时考虑key的自然排序或定制排序,底层使用红黑树
- HashTable:作为古老的实现类,线程安全,效率低,不能存储null的key和value
- properties:常用来处理配置文件,key和value都是Sting类型
HashMap的底层:
- jdk7及以前:数组+链表
- jdk8 数组+链表+红黑树
面试题:
HashMap底层实现原理
HashMap和HashTable区别
6.2Map结构的理解
- Map中的key:无序,不可重复,使用set存储所有的key(key所在的类要重写equals和hashCode方法)
- Map中的value:无序,可重复,使用Collection存储所有的value(value所在的类要重写equals)
- 一个键值对:key-value构成一个entry对象
- Map中的entry:无序不可重复,使用set存储所有的entry
6.3 Has和Map底层实现原理,以jdk7为例
HashMap的内部存储结构其实是数组和链表的结合。
HashMap<Object, Object> map = new HashMap<>();实例化以后,底层创建一个长度为16的Entry[] table数组向HashMap中添加entry1(key,value),需要首先计算entry1中key的哈希值(根据key所在类的hashCode()计算得到),此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i。如果位置i上没有元素,则entry1直接添加成功。如果位置i上已经存在entry2(或还有链表存在的entry3,entry4),则需要通过循环的方法,依次比较entry1中key和其他的entry。如果彼此hash值不同,则直接添加成功(和原来的数据用链表的形式进行存储)。如果hash值不同,继续比较二者是否equals。如果返回值为true,则使用entry1的value去替换equals为true的entry的value。如果遍历一遍以后,发现所有的equals返回都为false,则entry1仍可添加成功(和原来的数据用链表的形式进行存储)。entry1指向原有的entry元素。
在不断添加的过程中会涉及到扩容问题,当超出临界值(且要存放的位置非空时),扩容,默认扩容到原来两倍,然后重新计算每个元素在数组中的位置
jdk8相较于jdk7底层实现方面的不同
- new HashMap()底层没有创建长度为16的数组
- jdk 8地磁场数组是Node[]而非Entry[]
- 首次调用put方法是,底层创建长度为16的数组
- jdk7的底层只有数组+链表,而jdk8底层是数组+链表+红黑树(当数组某个位置上的元素以链表的形式存在数据的个数》8且当前数组的个数大于64时,此时索引位置上所有数据改为红黑树存储)
HashMap源码中的重要常量
- DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
- MAXIMUM_CAPACITY : HashMap的最大支持容量,2^30
- DEFAULT_LOAD_FACTOR:HashMap的默认加载因子 0.75
- THRESHOLD:扩充的临界值=容量+扩充因子 16*0.75 >=12
- TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树
- UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表
- MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。
6.4LinkHashMap底层原理
- LinkedHashMap 是 HashMap 的子类
- 在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序
- 与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致
6.5Map常用方法
- 添加、删除、修改操作:
- Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
- void putAll(Map m):将m中的所有key-value对存放到当前map中
- Object remove(Object key):移除指定key的key-value对,并返回value
- void clear():清空当前map中的所有数据
- 元素查询的操作:
- Object get(Object key):获取指定key对应的value
- boolean containsKey(Object key):是否包含指定的key
- boolean containsValue(Object value):是否包含指定的value
- int size():返回map中key-value对的个数
- boolean isEmpty():判断当前map是否为空
- boolean equals(Object obj):判断当前map和参数对象obj是否相等
- 元视图操作的方法:
- Set keySet():返回所有key构成的Set集合
- Collection values():返回所有value构成的Collection集合
- Set entrySet():返回所有key-value对构成的Set集合
常用方法:添加,修改,删除,查询,长度
@Test
public void text8()
{
HashMap<Object, Object> hashMap = new HashMap<>();
//添加
hashMap.put("a",1);
hashMap.put("b",2);
hashMap.put("c",4);
System.out.println(hashMap);
//修改
hashMap.put("a",11);
System.out.println(hashMap);
//删除
Object a = hashMap.remove("a");
System.out.println(a);
Object d = hashMap.remove("d");
//删除数据不存在
System.out.println(d);
System.out.println(hashMap);
//map大小
System.out.println(hashMap.size());
//是否为空
System.out.println(hashMap.isEmpty());
//是否包含指定的key
System.out.println(hashMap.containsKey("b"));
//是否包含指定的value
System.out.println(hashMap.containsValue(2));
//返回所要key的set集合
Set<Object> keySet = hashMap.keySet();
System.out.println("所有的key");
for(Object k:keySet)
{
System.out.println(k);
}
System.out.println("所有的value");
//返回所要的vaule
Collection<Object> values = hashMap.values();
for(Object o:values)
{
System.out.println(o);
}
System.out.println("key-value");
//获取所有的key-value
//方式一
Set<Map.Entry<Object, Object>> entries = hashMap.entrySet();
Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();
while(iterator.hasNext())
{
Map.Entry<Object, Object> next = iterator.next();
System.out.println(next.getKey()+"----->"+next.getValue());
}
//方式二
for(Object o:keySet)
{
System.out.println(o+"-------------->>>"+hashMap.get(o));
}
}
6.6TreeMap排序
自然排序
person.java
package com.blb.com;
import java.util.Objects;
/**
* @author smilecb
* @date 2021/9/12 0012 11:22
*/
public class Person implements Comparable{
private int id;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public int compareTo(Object o) {
if(o instanceof Person)
{
Person p=(Person) o;
if(this.getId()!=p.getId())
{
return this.getId()<p.id?1:-1;
}
else
{
return this.getName().compareTo(p.getName());
}
}
return 0;
}
}
测试类
@Test
public void text9()
{
TreeMap treeMap = new TreeMap<>();
treeMap.put(new Person(1,"shangsan"),70);
treeMap.put(new Person(3,"lisi"),60);
treeMap.put(new Person(1,"wangwu"),80);
treeMap.put(new Person(2,"cb"),66);
Set set = treeMap.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext())
{
Object next = iterator.next();
System.out.println(next+"---->"+treeMap.get(next));
}
}
定制排序
@Test
public void text10()
{
Comparator<Object> objectComparator = new Comparator(
) {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person && o2 instanceof Person)
{
Person p1=(Person) o1;
Person p2=(Person) o2;
if(!p1.getName().equals(p2.getName()))
return p1.getName().compareTo(p2.getName());
else
return p1.getId()-p2.getId();
}
return 0;
}
};
TreeMap treeMap = new TreeMap<>(objectComparator);
treeMap.put(new Person(1,"shangsan"),70);
treeMap.put(new Person(3,"lisi"),60);
treeMap.put(new Person(1,"wangwu"),80);
treeMap.put(new Person(2,"lisi"),66);
Set set = treeMap.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext())
{
Object next = iterator.next();
System.out.println(next+"---->"+treeMap.get(next));
}
}
6.7HashMap和HashTable区别
- Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的。
- Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。
- 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
- 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
- Hashtable判断两个key相等、两个value相等的标准,与HashMap一致。
6.8Properties
- Properties 类是 Hashtable 的子类,该对象用于处理属性文件
- 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型
- 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法
7. Collections工具类
- Collections 是一个操作 Set、List 和 Map 等集合的工具类
- Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
7.1Collection和Collections区别
Collection是一个接口,而Collections是操作Collection和Map一个工具类
7.2常用方法
方法名 | 描述 |
---|---|
reverse(List) | 反转 List 中元素的顺序 |
shuffle(List) | 对 List 集合元素进行随机排序 |
sort(List) | 根据元素的自然顺序对指定 List 集合元素按升序排序 |
sort(List,Comparator) | 根据指定的 Comparator 产生的顺序对 List 集合元素进行排序 |
swap(List,int, int) | 将指定 list 集合中的 i 处元素和 j 处元素进行交换 |
Object max(Collection) | 根据元素的自然顺序,返回给定集合中的最大元素 |
Object max(Collection,Comparator) | 根据 Comparator 指定的顺序,返回给定集合中的最大元素 |
Object min(Collection) | 根据元素的自然顺序,返回给定集合中的最小元素 |
Object min(Collection,Comparator) | 根据 Comparator 指定的顺序,返回给定集合中的最小元素 |
int frequency(Collection,Object) | 返回指定集合中指定元素的出现次数 |
void copy(List dest,List src) | 将src中的内容复制到dest中 boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值 |
Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题