Java集合部分总结

本篇文章的目的
梳理Java集合知识
简单介绍各个组成部分

如有错误,请一定指出,手动笑脸。


集合结构图
集合结构图

看到array,就要想到角标。
看到link,就要想到first,last。
看到hash,就要想到hashCode,equals.
看到tree,就要想到两个接口。Comparable(可比较),Comparator(比较器)。

List

ArrayList

ArrayList是List的子接口,List是Collection的子接口

List接口: 有序的、不唯一
ArrayList: 有序的、不唯一

数据结构: Object数组


ArrayList的基本用法和特点

特点:
    有序的:按照添加的顺序排列
    可重复:同一个元素可以装多次
1:如何创建集合泛型对象

ArrayList<泛型> list=new ArrayList<>();

2:如何添加元素:

	一次添加一个元素:
	list.add(元素);
	
	一次添加多个元素:
	Collections.addAll(集合,元素,元素,...);
	
3:得到集合元素的个数
	
	list.size();
	
4:得到某一个元素
	
	list.get(下标);
	
5:如何判断集合里面是否出现指定元素
	
	list.contains();
	
6:遍历

	for+下标
	for(int x=0;x<list.size();x++){
	    //x->下标
	    //list.get(元素);
	}
	
	foreache
	for(集合的泛型 x :list){
	    //x->元素
	}
	
	迭代器********(重点)
	for(得到迭代器对象;判断迭代器上面是否还有下一个元素;){
					取出下一个元素
				  }
	实例
	for(Iterator<泛型>car=list.iterator();car.hasNext;){
	    car.next();->元素
}

ArrayList 如何删除元素:

list.remove(int 下标);
	下标指向谁就删除谁,如果下标不存在就抛出异常。

清空集合:list.clear();

ArrayList其他细节

1:ArrayList类里面的remove(元素)的方法底层需要遵从equals比较机制

		当我们想要删除一个元素的时候 底层拿着这个元素和集合里面的每一个元素做equals比较

2:谁主张谁举证

		要被删除的对象会主动调用他自己类的equals方法和集合里面的每一个元素做比较 

3:当我们使用迭代器遍历集合的过程中,不允许对集合的整体进行添加、删除操作,否则出发CME异常

		如果想要在遍历的过程中进行删除,只能使用迭代器的删除方法:car.remove();

4:构造方法:
		ArrayList list = new ArrayList(int 数组空间大小);
		ArrayList list = new ArrayList();//数组默认开辟10块空间

		集合会自动扩容:
			jdk6.0及之前	x * 3 / 2 + 1
							10 -> 16 -> 25....

			jdk7.0及之后	x + (x >> 1)
							10 -> 15 -> 22....

		在项目开发的时候 尽量避免扩容:
			1:创建一个更大的新的数组对象
			2:将老数组里面的元素复制到新数组里面
			3:改变引用指向
			4:回收老数组对象
			5:继续添加元素

		扩容:list.ensureCapacity(数组空间)
		缩容:list.trimToSize()

 **************************************
Vector语法和ArrayList一模一样的
 **************************************
面试题:
ArrayList和Vector之间的区别?
1:同步特性不同
Vector同一时间允许一个线程进行访问,效率较低,但是不会发生并发错误。
ArrayList同一时间允许多个线程进行访问,效率高,但是可能会发生并发错误。
 **************************************
jdk5.0开始 集合的工具类[Collections]里面提供一个方法synchronizedList
	   可以将线程不安全的ArrayList集合变成线程安全的集合对象
	   于是Vector渐渐被淘汰了
2:扩容不同
ArrayList:分版本
		jdk6.0及之前	x * 3 / 2 + 1
		jdk7.0及之后	x + (x >> 1)

Vector:分构造方法
		Vector(10) -> 2倍扩容	10 -20 -40...
		Vector(10,3) -> 定长扩容 10 -13 -16...

3:出现的版本不同
	  Vector:since jdk1.0
	  ArrayList:since jdk1.2
 **************************************
 LinkedList语法和ArrayList一模一样
	面试题: 
    ArrayList和LinkedList之间的区别?
	     ArrayList和LinkedList底层数据结构不同 导致优劣势不同 
	     
	     ArrayList:底层是基于数组实现的
		    优点:随机访问 遍历查找效率高
		    缺点:添加删除元素的时候效率低
	     
	     LinkedList:底层是基于链表实现的
		     优点:添加删除元素的时候效率高。
		     缺点:随机访问 遍历查找效率低[从下标0开始找起]
**************************
Stack: 用数组模拟栈结构

LinkedList

LinkedList是List的子接口,List是Collection的子接口,和ArrayList同一层

从底层来看:
1. Array底层是Object[]
2. LinkedList底层是双向链表

链表结构也就意味着LinkedList更适合数据更新频繁的环境,因为LinkedList不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,类似于插入数据,删除数据时,LinkedList也优于ArrayList,其时间复杂度仅为O(1)

而且ArrayList删除数据是开销很大的,因为这需要重排数组中的所有数据(除了最后一个元素)。

下面来看看LinkedList的一些常用方法。


基本特点:

  1. 非同步,线程不安全;
  2. 支持null元素,元素可以重复;
  3. 可以被当作堆栈、队列或双端队列进行操作。
  4. 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
  5. LinkedList包含两个重要的成员:header 和 size。
 		header是双向链表的表头,它是双向链表节点所对应的类Entry的实例。
 		Entry中包含成员变量: previous, next, element。
		
			previous是该节点的上一个节点,
			next是该节点的下一个节点,
			element是该节点所包含的值。 
		 	
	 	size是双向链表中节点的个数。

使用场景:

LinkedList适用于对数据进行频繁的修改操作的场景。


Set

Set:注重独一无二的性质,该体系集合可以知道元素是否已经存在于集合中,不会存储重复的元素

特点:

  • 存储时元素无序(存入和取出的顺序不一定相同)
  • 值不能重复。

对象的相等性

  • 引用到堆上同一个对象的两个引用是相等的。如果对两个引用调用hashCode方法,会得到相同的结果,如果对象所属的类没有覆盖Object的hashCode方法的话,hashCode会返回每个对象特有的序号(java是依据对象的内存地址计算出的此序号),所以两个不同的对象的hashCode值是不可能相等的。

如果想要让两个不同的Person对象视为相等的,就必须覆盖Object继下来的hashCode方法和equals方法;

因为Object 下的hashCode方法返回的是该对象的内存地址,所以必须重写hashCode方法(即换一种与重写后的equals判断相等条件相关的条件,来生成新的hashCode),才能保证两个不同的对象具有相同的hashCode,同时也需要两个不同对象比较equals方法会返回true

该集合中没有特有的方法,直接继承自Collection。

案例:set集合添加元素并使用迭代器迭代元素,测试无序性、不可重复性。

public class Demo4 {
	public static void main(String[] args) {
		//Set 集合存和取的顺序不一致。
		Set hs = new HashSet();
		hs.add("世界军事");
		hs.add("兵器知识");
		hs.add("舰船知识");
		hs.add("兵器知识");
		hs.add("历史知识");
		hs.add("动物知识");
		System.out.println(hs);
		// [世界军事, 历史知识, 动物知识, 兵器知识, 舰船知识]
		Iterator it = hs.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
}

结果

[世界军事, 历史知识, 动物知识, 兵器知识, 舰船知识]
世界军事
历史知识
动物知识
兵器知识
舰船知识


HashSet

哈希表边存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。

由于Set集合是不能存入重复元素的集合,那么HashSet也是具备这一特性的。

HashSet如何检查重复?

HashSet会通过元素的hashcode()和equals方法进行判断元素师否重复。

当对象加入集合时,HashSet会使用对象的hashCode来判断对象加入的位置。同时也会与其他已经加入的对象的hashCode进行比较

  • 如果没有相等的hashCode,HashSet就会假设对象没有重复出现;
  • 如果元素hashCode值相同,是不是就无法存入HashSet中了? 当然不是,会继续使用equals 进行比较。如果 equals为true 那么HashSet认为新加入的对象重复了,所以加入失败。如果equals 为false那么HashSet 认为新加入的对象没有重复。新元素可以存入。
    • 哈希值相同equals为false的元素是怎么存储呢?
    • 就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。
      在这里插入图片描述

图1:hashCode值不相同的情况

图2:hashCode值相同,但equals不相同的情况。

总结:

元素的哈希值是通过元素的hashcode方法 来获取的,放数据时,HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equls结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。


扩展

HashSet 和ArrayList集合都有判断元素是否相同的方法,
boolean contains(Object o)
HashSet使用hashCode和equals方法,ArrayList使用了equals方法

例子:使用HashSet存储自定义对象,并尝试添加重复对象(对象不可重复的判定)

package ttest;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetDemo {

	public static void main(String[] args) {
		
		Set<Person> hs = new HashSet<Person>();
		hs.add(new Person("tom",18));
		hs.add(new Person("jerry",18));
		hs.add(new Person("maks",19));
		hs.add(new Person("maks",19));
		hs.add(new Person("jimi",18));
		
		Iterator it = hs.iterator();
		while(it.hasNext()) {
			Object per = it.next();
			System.out.println(per);
		}
	}
	
}

class Person{
	
	private String name;
	private Integer age;
	
	public Person() {
		super();
	}

	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int hashCode() {
		System.out.println("hashCode:" + this.name);
		return this.name.hashCode() + age * 13;
	}

	@Override
	public boolean equals(Object obj) {
		System.out.println(this + " equals " + obj);
		
		if(obj instanceof Person) {
			Person p = (Person)obj;
			return this.name.equals(p.name) && this.age == p.age;
		}else {
			return false;
		}
	}	
}

结果

hashCode:tom
hashCode:jerry
hashCode:maks
hashCode:maks
Person [name=maks, age=19] equals Person [name=maks, age=19]
hashCode:jimi
Person [name=maks, age=19]
Person [name=jimi, age=18]
Person [name=tom, age=18]
Person [name=jerry, age=18]

从结果来看,可以保证唯一,但不保证有序。

问题:现在有一批数据,要求不能重复存储元素,而且要排序。ArrayList 、 LinkedList不能去除重复数据。HashSet可以去除重复,但是是无序。

所以这时候就要使用TreeSet了

TreeSet

public class Demo5 {
	public static void main(String[] args) {
		TreeSet ts = new TreeSet();
		ts.add("ccc");
		ts.add("aaa");
		ts.add("ddd");
		ts.add("bbb");
 
		System.out.println(ts); // [aaa, bbb, ccc, ddd]
	}
}

红黑树

红黑树是一种特定类型的二叉树
在这里插入图片描述
红黑树算法的规则: 左小右大。

既然TreeSet可以自然排序,那么TreeSet必定存在排序规则的

  1. 让存入的元素自定义比较规则。

  2. 给TreeSet指定排序规则。

实现排序的两种措施

方式一:元素自身具备比较性

元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,(当compareTo()函数返回值为0时,说明两个对象相等,此时该对象不会添加进来)也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

方式二:容器具备比较性

当元素自身不具备比较性,或者自身具备的比较性不是所需要的,那么此时可以让容器自身具备比较性。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。

注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)

通过return 0来判断唯一性。

比较器接口

----| Comparable
       		compareTo(Object o)     元素自身具备比较性
----| Comparator
       		compare( Object o1, Object o2 )	给容器传入比较器

方式一

  • 让元素自身具备比较性,也就是元素需要实现Comparable接口,覆盖compareTo 方法。

例子

package testset;

import java.util.Set;
import java.util.TreeSet;

public class TreeSetDemo {

	public static void main(String[] args) {
		
		Set<Person1> ts = new TreeSet<Person1>();
		ts.add(new Person1("aa", 20, "男"));
		ts.add(new Person1("bb", 18, "女"));
		ts.add(new Person1("cc", 17, "男"));
		ts.add(new Person1("dd", 17, "女"));
		ts.add(new Person1("dd", 15, "女"));
		ts.add(new Person1("dd", 15, "女"));
 
		System.out.println("**********************************");
		System.out.println(ts);
		System.out.println("**********************************");
		System.out.println(ts.size()); // 5		
	}	
}

class Person1 implements Comparable{
	
	private String name;
	private Integer age;
	private String gender;
	
	public Person1(String name, Integer age, String gender) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
	}
	
	public Person1() {
		super();
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
		
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
	}
	
	@Override
	public int hashCode() {
		return this.name.hashCode() + age * 13;
	}

	@Override
	public boolean equals(Object obj) {
		
		System.err.println(this + "equals :" + obj);
		if (!(obj instanceof Person)) {
			return false;
		}
		Person1 p = (Person1) obj;
		return this.name.equals(p.name) && this.age == p.age;
	}

	@Override
	public int compareTo(Object obj) {
		
		Person1 p = (Person1)obj;
		System.out.println(this+" compareTo:"+p);
		if (this.age > p.age) {
			return 1;
		}
		if (this.age < p.age) {
			return -1;
		}
		return this.name.compareTo(p.name);
	}
}

结果(有手动调整间隙)

Person [name=aa, age=20, gender=男] compareTo:Person [name=aa, age=20, gender=男]

Person [name=bb, age=18, gender=女] compareTo:Person [name=aa, age=20, gender=男]

Person [name=cc, age=17, gender=男] compareTo:Person [name=aa, age=20, gender=男]
Person [name=cc, age=17, gender=男] compareTo:Person [name=bb, age=18, gender=女]

Person [name=dd, age=17, gender=女] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=17, gender=女] compareTo:Person [name=cc, age=17, gender=男]

Person [name=dd, age=15, gender=女] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=15, gender=女] compareTo:Person [name=cc, age=17, gender=男]

Person [name=dd, age=15, gender=女] compareTo:Person [name=bb, age=18, gender=女]
Person [name=dd, age=15, gender=女] compareTo:Person [name=cc, age=17, gender=男]
Person [name=dd, age=15, gender=女] compareTo:Person [name=dd, age=15, gender=女]
**********************************
[
	Person [name=dd, age=15, gender=女], 
	Person [name=cc, age=17, gender=男], 
	Person [name=dd, age=17, gender=女], 
	Person [name=bb, age=18, gender=女], 
	Person [name=aa, age=20, gender=男]
]
**********************************
5

方式二

  • 让容器自身具备比较性,自定义比较器。
  • 当元素自身不具备比较性,或者元素自身具备的比较性不是所需的,那么这时只能让容器自身具备。
  • 定义一个类实现Comparator 接口,覆盖compare方法,并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。

例子

package testset;

import java.util.Comparator;
import java.util.TreeSet;

public class Demo5 {
	public static void main(String[] args) {
		TreeSet ts = new TreeSet(new MyComparator());
		ts.add(new Book("think in java", 100));
		ts.add(new Book("java 核心技术", 75));
		ts.add(new Book("现代操作系统", 50));
		ts.add(new Book("java就业教程", 35));
		ts.add(new Book("think in java", 100));
		ts.add(new Book("ccc in java", 100));
 
		System.out.println(ts); 
	}
}
 
// 比较器
class MyComparator implements Comparator {
 
	public int compare(Object o1, Object o2) {
		Book b1 = (Book) o1;
		Book b2 = (Book) o2;
		System.out.println(b1+" comparator "+b2);
		if (b1.getPrice() > b2.getPrice()) {
			return 1;
		}
		if (b1.getPrice() < b2.getPrice()) {
			return -1;
		}
		return b1.getName().compareTo(b2.getName());
	} 
}
 
class Book {
	private String name;
	private double price;
 
	public Book() {
 
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public double getPrice() {
		return price;
	}
 
	public void setPrice(double price) {
		this.price = price;
	}
 
	public Book(String name, double price) {
 
		this.name = name;
		this.price = price;
	}
 
	@Override
	public String toString() {
		return "Book [name=" + name + ", price=" + price + "]";
	}
 
}

结果(有手动调整间距)

Book [name=think in java, price=100.0] comparator Book [name=think in java, price=100.0]

Book [name=java 核心技术, price=75.0] comparator Book [name=think in java, price=100.0]

Book [name=现代操作系统, price=50.0] comparator Book [name=think in java, price=100.0]
Book [name=现代操作系统, price=50.0] comparator Book [name=java 核心技术, price=75.0]

Book [name=java就业教程, price=35.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=java就业教程, price=35.0] comparator Book [name=现代操作系统, price=50.0]

Book [name=think in java, price=100.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=think in java, price=100.0] comparator Book [name=think in java, price=100.0]

Book [name=ccc in java, price=100.0] comparator Book [name=java 核心技术, price=75.0]
Book [name=ccc in java, price=100.0] comparator Book [name=think in java, price=100.0]

[
	Book [name=java就业教程, price=35.0],
	Book [name=现代操作系统, price=50.0], 
	Book [name=java 核心技术, price=75.0],
	Book [name=ccc in java, price=100.0], 
	Book [name=think in java, price=100.0]
 ]

LinkedHashSet

会保存插入的顺序


Map

什么是Map集合?

Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组用于保存Map的ley,另一组保存着Map的value。

图解在这里插入图片描述
Map集合的作用

和查字典类似,通过key找到对应的value,通过页数找到对应的信息。用学生类来说,key相当于学号,value对应name,age,sex等信息。用这种对应关系方便查找。

Map和Set的关系

可以说关系是很密切了,虽然Map中存放的是键值对,Set中存放的是单个对象,但如果把value看做key的附庸,key在哪里,value就在哪里,这样就可以像对待Set一样来对待Map了。事实上,Map提供了一个Entry内部类来封装key-value对,在计算Entry存储时则只考虑Entry封装的key。

如果把Map集合里的所有value放在一起来看,它们又类似于一个List,元素可以重复,每个元素可以根据索引来找,只是Map中的索引不再是整数值,而是以另一个对象作为索引。

Map用法

类型介绍
Java 自带了各种 Map 类,这些 Map 类可归为三种类型:

  1. 通用Map,用于在应用程序中管理映射,通常在 java.util 程序包中实现

HashMap、Hashtable、Properties、LinkedHashMap、IdentityHashMap、TreeMap、WeakHashMap、ConcurrentHashMap

  1. 专用Map,通常我们不必亲自创建此类Map,而是通过某些其他类对其进行访问

java.util.jar.Attributes、javax.print.attribute.standard.PrinterStateReasons、java.security.Provider、java.awt.RenderingHints、javax.swing.UIDefaults

  1. 一个用于帮助我们实现自己的Map类的抽象类

AbstractMap

类型区别

HashMap

  • 最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。

TreeMap

  • 能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。

Hashtable

  • 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

LinkedHashMap

  • 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。

Map 初始化
Map<String, String> map = new HashMap<String, String>();

插入元素
map.put("key1", "value1");

获取元素
map.get("key1")

移除元素
map.remove("key1");

清空map
map.clear();

Map 遍历

初始化数据

Map<String, String> map = new HashMap<String, String>();
 
map.put("key1", "value1");
 
map.put("key2", "value2");

增强for循环遍历

使用keySet()遍历

for (String key : map.keySet()) {
 
    System.out.println(key + " :" + map.get(key));
 }

使用entrySet()遍历

for (Map.Entry<String, String> entry : map.entrySet()) {
 
    System.out.println(entry.getKey() + " :" + entry.getValue());
 
}

迭代器遍历

使用keySet()遍历

Iterator<String> iterator = map.keySet().iterator();
 
while (iterator.hasNext()) {
 
    String key = iterator.next();
 
    System.out.println(key + " :" + map.get(key));
 }

使用entrySet()遍历

Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
 
while (iterator.hasNext()) {
 
    Map.Entry<String, String> entry = iterator.next();
 
    System.out.println(entry.getKey() + " :" + entry.getValue());
 
}

测试性能参考:Java map集合深入学习

直接给出结论

  • 增强for循环使用方便,但性能较差,不适合处理超大量级的数据。

  • 迭代器的遍历速度要比增强for循环快很多,是增强for循环的2倍左右。

  • 使用entrySet遍历的速度要比keySet快很多,是keySet的1.5倍左右。

内部各类

HashMap和Hashtable的关系完全类似于ArrayList和Vector的关系

  • Hashtable是线性安全的,HashMap是线性不安全的,所以后者效率更高。
  • Hashtable不允许使用null作为key和value,否则会引发异常,而HashMap可以;

和HashSet的关系

  • 与HashSet集合不能保证元素顺序一样,HashMap和Hashtable也不能保证键值对的顺序。他们判断两个key相等的标准也是:两个key通过equals方法比较返回true,两个key的hashCode值也相等。而判断value值相等的标准:只要两个对象通过equals方法比较返回true即可。
  • 不能修改集合中的key,否则程序再也无法准确访问到Map中被修改过的key。

LinkedHashMap实现类

  • 和HashSet中的LinkedHashSet一样,HashMap也有一个LinkedHashMap子类,使用双向链表来维护键值对的次序,迭代顺序和插入顺序保持一致。

SortedMap接口和TreeMap实现类

  • 正如Set接口派生出SortedSet子接口,Sorted接口有一个TreeSet实现类一样,Map接口也派生出一个SortedMap子接口,SortedMap接口也有一个TreeMap实现类。

TreeMap就是一个红黑树数据结构,每个键值对作为红黑树的一个节点。存储键值对时根据key对节点进行排序。可以保证所有键值对处于有序状态。

和TreeSet一样,TreeMap也有自然排序和定制排序两种排序方式。

public static void main(String[] args) {
        TreeMap<String, Integer> stuTreeMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int num=o1.compareTo(o2);
                return num;
            }
        });


        stuTreeMap.put("LiMing",14);
        stuTreeMap.put("LiMing",24);
        stuTreeMap.put("Jenny",16);
        stuTreeMap.put("Denny",24);

        System.out.println(stuTreeMap);//{Denny=24, Jenny=16, LiMing=24}
        
        System.out.println(stuTreeMap.firstEntry());//Denny=24

    }

参考:java中的Map集合
参考:Java面试题–集合各实现类的底层实现原理
参考:这几道Java集合框架面试题在面试中几乎必问
参考:集合各实现类的底层实现原理
参考:HashMap底层实现原理及面试问题
参考:Arraylist
参考:LinkedList
参考:Java Set集合的详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值