早在 Java 2 中之前,Java 就提供了特设类。比如:Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组。
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
List 接口
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
package com.hspedu.collection_;
import java.util.ArrayList;
import java.util.HashMap;
/**
* @author 山河与you皆无恙
*/
public class Collection_ {
@SuppressWarnings("all")
public static void main(String[] args) {
//1.集合主要是两组(单列集合,双列集合)
//2.Collection 接口有两个重要的子接口 List Set,他们的实现子类都是单列集合
//3.Map 接口的实现子类是 双列集合,存放的 K-V
//4.两张图很重要,需要记住
//Collection
//Map
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("tom");
HashMap hashMap = new HashMap();
hashMap.put("NO1","北京");
hashMap.put("NO2","上海");
}
}
List 方法使用
package com.hspedu.collection_;
import java.util.ArrayList;
import java.util.List;
/**
* @author 山河与you皆无恙
*/
public class CollectionMethod {
@SuppressWarnings("all")
public static void main(String[] args) {
List list = new ArrayList();
// add:添加某个元素
list.add("jack");
list.add(10);//list.add(new Integer(10))
list.add(true);
System.out.println("List"+list);
// remove:删除指定元素
// list.remove(0);//删除第一个元素
list.remove(true);
// cotains:查找元素是否存在
System.out.println(list.contains("jack"));
// size:获取元素个数
System.out.println(list.size());
// isEmpty:判断元素是否为空
System.out.println(list.isEmpty());
// clear:清空
list.clear();
System.out.println("List"+list);
// addall:
ArrayList list2 = new ArrayList();
list2.add("红楼梦");
list2.add("三国演义");
list.addAll(list2);
System.out.println("List"+list);
// containsall:查找多个元素是否存在
System.out.println(list.containsAll(list2));//true
list.add("聊斋");
// removeall:删除多个元素
list.removeAll(list2);
System.out.println("List"+list);
// 说明:以ArrayList实现来演示
}
}
增强for和迭代器遍历
package com.hspedu.collection_;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author 山河与you皆无恙
*/
public class CollectionFor {
@SuppressWarnings("all")
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义","罗贯中",10.1));
col.add(new Book("小李飞刀","古龙",10.1));
col.add(new Book("红楼梦","曹雪芹",34.6));
//1.使用增强for,在Collection集合
//2.增强for,底层仍然是迭代器
//3.增强for可以理解为简化版的迭代器遍历
//4.快捷键 I
// for (Object book:col) {
// System.out.println("Book"+book);
// }
for (Object o :col) {
System.out.println("Book"+o);
}
}
}
package com.hspedu.collection_;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author 山河与you皆无恙
*/
public class CollectionIterator {
@SuppressWarnings("all")
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义","罗贯中",10.1));
col.add(new Book("小李飞刀","古龙",10.1));
col.add(new Book("红楼梦","曹雪芹",34.6));
//1.遍历集合
System.out.println("col="+col);
//先得到 Iterator的迭代器
Iterator iterator = col.iterator();
//2.使用while循环遍历
// while (iterator.hasNext()) {//判断是否还有数据
// //返回下一个元素,类型是 Object
// Object obj = iterator.next();
// System.out.println("obj"+obj);
//
// }
//快捷键生成 while循环遍历=》itit+enter(即回车)
//显示所有快捷键的快捷键 ctrl+j
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj"+obj);
}
//当退出while以后,这时iterator迭代器指向最后的元素
//iterator.next();//NoSuchElmentException
//如果需要再次遍历,需要重置我们的迭代器
iterator = col.iterator();
System.out.println("=======第二次遍历=======");
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj"+obj);
}
}
}
class Book{
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + ''' +
", author='" + author + ''' +
", price=" + price +
'}';
}
}
collections
java.util.Collections 是一个包装类。它包含有各种有关集合操作的 静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
package com.hspedu.collections_;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class Collections_ {
//创建 ArrayList 集合 用于测试
public static void main(String[] args) {
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
list.add("milan");
System.out.println("list= "+list);
//reverse(list):反转list中的元素的是顺序
Collections.reverse(list);
//shuffle(list):对list中的元素进行随机排序
System.out.println("list= "+list);
// for (int i = 0; i <5 ; i++) {
// Collections.shuffle(list);
// System.out.println("list= "+list);
// }
//sort(list):对集合list中的元素自然排序
Collections.sort(list);
System.out.println("list= "+list);
//按照字符串长度比较
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o1).length()-((String)o2).length();
}
});
System.out.println("字符串长度大小= "+list);
//将指定 list 集合中的i 处元素和j处元素进行交换
//wap(list,1,2)
Collections.swap(list,1,2);
System.out.println("交换后= "+list);
//Object max(Collectionn):根据元素自然排序,返回给定集合中的最大元素
System.out.println("自然排序最大元素="+Collections.max(list));
//比如返回最大的元素
//根据Comparator指定的顺序,返回给定集合中的最大元素
Object maxObject = Collections.max(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o1).length()-((String)o2).length();
}
});
System.out.println("长度最大的元素="+maxObject);
//int frequency(Collection,Object)) 返回指定集合中指定元素的出现次数
System.out.println("tom出现的次数="+Collections.frequency(list,"tom"));
//void copy(List dest,List src) 将src中的内容复制到dest中
ArrayList dest = new ArrayList();
//为了完成完整拷贝,先给 dest 赋值,大小和 list,size()大小一样
for (int i = 0; i <list.size() ; i++) {
dest.add("");
}
//拷贝
Collections.copy(dest,list);
System.out.println("dest="+dest);
//boolearn replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
boolean b = Collections.replaceAll(list, "tom", "汤姆");
System.out.println("list替换后= "+list);
}
}
ArrayList
该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。
ArrayList执行过程
package com.hspedu.list_;
import java.util.ArrayList;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class ArrayListSource {
public static void main(String[] args) {
//注意,注意,注意,idea 默认情况下, Debug 显示的数据是简化后的,如果希望看到完整的数据需要做设置
//使用无参构造器创建 ArrayList 对象
//ArrayList list = new ArrayList();
ArrayList list = new ArrayList(8);
//使用for给list集合添加1—10数据
for (int i = 0; i <=10 ; i++) {
list.add(i);
}
//用for给list集合添加11-15
// 数据
for (int i = 11; i <15 ; i++) {
list.add(i);
}
list.add(100);
list.add(200);
list.add(null);
}
}
LinkedList
该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如:
List list=Collections.synchronizedList(newLinkedList(…));
LinkedList 查找效率低。
package com.hspedu.list_;
import java.util.Iterator;
import java.util.LinkedList;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class LinkedListCRUD {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
System.out.println("linkedList"+linkedList);
//演示一个删除结点的
linkedList.remove();//这里默认删除的是第一个结点
System.out.println("linkedList"+linkedList);
//修改某个结点对象
linkedList.set(1,999);
System.out.println("linkedList"+linkedList);
//得到某个结点的对象
//get(1)是得到双向链表的第二个对象
Object o = linkedList.get(1);
System.out.println(0);
//因为linkedList是实现了list接口方式,遍历方式
System.out.println("=============linedList遍历迭代器============");
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
System.out.println("=============linedList遍历增强for============");
for (Object o1 :linkedList) {
System.out.println("o1=0"+o1);
}
System.out.println("=============linedList遍历普通for============");
for (int i = 0; i <linkedList.size() ; i++) {
System.out.println(linkedList.get(i));
}
/*//1.LinkedList linkedList = new LinkedList();
public LinkedList {}
2.这时LinkedList的属性 first =null last =null
3. 执行、添加
public boolean add(E e) {
linkLast(e);
return true;
}
4.
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
*/
/* linkedList.remove();//这里默认删除的是第一个结点
1.执行
public E remove() {
return removeFirst();
}
2.执行
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
3.执行 unlinkFirst 将f指向的第一个结点拿掉
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
*/
}
}
Set
Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。
Set 接口存储一组唯一,无序的对象。
HashSet
该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。
package com.hspedu.set_;
import java.util.HashSet;
import java.util.Set;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class HashSet_ {
public static void main(String[] args) {
/* 1.构造器走的源码
2.HashSet 可以存放null 但是只能有一个null,即元素不能重复
*/
Set hashSet = new HashSet();
hashSet.add(null);
hashSet.add(null);
System.out.println("hashSet= "+hashSet);
}
}
package com.hspedu.set_;
import java.util.HashSet;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class HashSetSource {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
hashSet.add("java");
hashSet.add("php");
hashSet.add("java");
System.out.println("set="+hashSet);
/*
1.执行HashSet()
public HashSet() {
map = new HashMap<>();
}
2.执行add()
public boolean add(E e) {//e="java"
return map.put(e, PRESENT)==null;//(static) PRESENT = new Object();
}
3.执行put(),该方法会执行 hash(key)得到 key 对应的 hash 值 算法(h = key.hashCode()) ^ (h >>> 16)
public V put(K key, V value) {//key="java" value = PRESENT 共享
return putVal(hash(key), key, value, false, true);
}
4.执行
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;//定义了辅助变量
//table 就是 HashMap 的一个数组,类型是 Node[]
//if语句表示如果当前 table 是null,或者大小=0
//就是第一次扩容到16个空间
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//(1)根据key 得到hash 去计算该key应该存放到索引表的哪个索引位置
//并把这个位置的对象赋给p
//(2)判断 p 是否为null
//(2.1)如果 p 为null,表示还没有存放元素,就创建一个 Node(Key = "java",value = PRESENT)
//(2.2)就放在该位置tab[i] = newNode(hash, key, value, null)
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
//一个开发技巧提示,:在创建局部变量(辅助变量)的时候,在创建
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
*/
}
}
Vector
该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。
package com.hspedu.list_;
import java.util.Vector;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class Vector_ {
public static void main(String[] args) {
// Vector vector = new Vector();
Vector vector = new Vector(8);
for (int i = 0; i <=10; i++) {
vector.add(i);
}
/*
//1.Vector底层
public Vector() {
this(10);
}
//2.Vector.add()
//2.1添加数据到Vector集合
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
补充:如果是Vector vector = new Vector(8)
走的方法
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
//确定是否需要扩容 条件:minCapacity - elementData.length > 0
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//如果需要的数组大小不够用,就扩容,扩容的算法,就是扩容2倍
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
*/
}
}
Map
Map 接口存储一组键值对象,提供key(键)到value(值)的映射。
package com.hspedu.map_;
import java.util.HashMap;
import java.util.Map;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class Map_ {
public static void main(String[] args) {
//Map实现类的特点,使用实现类HashMap
//1.Map与Collection并列存在,用于保存具有映射关系的数据:key-value(双列元素)
//2.Map 中的 key 和 value 可以是任何类型的数据,会封装到 HashMap$Node 对象中
//3.Map 中的 key 不允许重复,原因和 HashSet 一样,前面源码已经分析
//4.Map 中的 value 可以重复
//5.注意:Map 中的 key 可以为null,value也可以为null, Map 中的key为null只能有一个,value为null可以多个
//6.常用String类作为Map的key
Map map = new HashMap();
map.put("no1","韩顺平");//k-v
map.put("no2","张无忌");//k-v
map.put("no1","张三丰");//k-v 当有相同的 k,就等价于替换。
map.put("no3","张三丰");//k-v
map.put(null,null);//k-v
map.put(null,"abc");//k-v 等价替换
map.put("no4",null);//k-v
map.put("no5",null);//k-v
System.out.println("map="+map);
//通过get方法 传入 key,会返回对应的 value
System.out.println(map.get("no2"));
}
}
HashMap
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。
package com.hspedu.map_;
import java.util.HashMap;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class HashMapSource1 {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
hashMap.put("java",10);
hashMap.put("php",10);
hashMap.put("java",20);
System.out.println("hashMap="+hashMap);
/*
1.执行构造器 new HashMap
初始化加载因子 loadFactor
HashMap$Node[] table = null
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
2.执行put 调用Hash方法,计算 key的hash值 (h = key.hashCode()) ^ (h >>> 16)
public V put(K key, V value) {//key="java" value =10
return putVal(hash(key), key, value, false, true);
}
3.执行 putVal
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果底层的table数组为null,或者 length = 0就扩容到16
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//取出hash值对应的table索引位置的Node,如果为null,就直接把加入的k-v
//,创建成一个Node,加入该位置即可
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;//辅助变量
//如果 table 的索引位置的key的hash值和新的key的hash值相同
//并满足(table 现有结点的key和准备添加的key是同一个对象 || equals 返回真)
//就认为不能加入行的key
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)//如果当前的table的已有的 Node 是红黑树,就按照红黑树的方式处理
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {//如果找到的结点,后面是链表,就循环比较
for (int binCount = 0; ; ++binCount) {//死循环
if ((e = p.next) == null) {//如果整个链表没有和它相同,就加到链表的最后,
p.next = newNode(hash, key, value, null);
//加入后 就判断当前链表的个数,是否已经到8个,后
//就调用 treeifyBin 方法进行红黑树转换
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&//如果在循环比较过程中,发现有相同,就 break,就只是替换 value
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;//替换 key 对应的值
afterNodeAccess(e);
return oldValue;
}
}
++modCount;//没增加一个 Node,就size++
if (++size > threshold)//如size>临界值(12-24-48----),就扩容
resize();
afterNodeInsertion(evict);
return null;
}
5.关于树化(转成红黑树)
//如果 table 为 null 或者大小还没有到 64 暂时不树化,而是进行扩容
//否则才会真正的树化->剪枝
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
*/
}
}
遍历方式
package com.hspedu.map_;
import java.util.*;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("邓超",new Book("",100));//ok
map.put("邓超","孙俪");//替换
map.put("王宝强","马蓉");//ok
map.put("宋喆","马蓉");//ok
map.put("刘令博",null);//ok
map.put(null,"刘亦菲");//ok
map.put("鹿晗","关晓彤");//ok
System.out.println("map= "+map);
//1.第一组:先取出所有的key,通过key取出对应的value
//(1)增强for
System.out.println("================第一种方式================");
Set keySet = map.keySet();
for (Object key : keySet) {
System.out.println(key+"-"+map.get(key));
}
System.out.println("================第二种方式================");
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key+"-"+map.get(key));
}
//第二组:把所有的Values取出
Collection values = map.values();
//这里可以使用所有 Collection 的方法
//(1)增强for
System.out.println("=============取出所有的value 增强for(第1种)==============");
for (Object value :values) {
System.out.println(value);
}
//(2)迭代器
System.out.println("=============取出所有的value 迭代器(第2种)==============");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object value = iterator2.next();
System.out.println(value);
}
//第三组:通过EntreySet 来获取k—v
System.out.println("=============使用EntrySet的for增强(第3种)==============");
Set entrySet = map.entrySet();
for (Object entry :entrySet) {
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey()+"-"+m.getValue());
}
//第四组:通过EntrySet的 迭代器来获取k—v
System.out.println("=============使用EntrySet的 迭代器(第4种)==============");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
Object entry = iterator3.next();
System.out.println(entry );//HashMap$Node->实现 Map.Entry(getKey,getValue)
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey()+"-"+m.getValue());
}
}
}
TreeMap
继承了AbstractMap,并且使用一颗树。
package com.hspedu.map_;
import java.util.Comparator;
import java.util.TreeMap;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class TreeMap_ {
public static void main(String[] args) {
//使用默认的构造器创建TreeMap 是无序
//按照传入的 k(String)的大小进行排序
//TreeMap treeMap = new TreeMap();
TreeMap treeMap = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//按照传入的 k(String)的大小进行排序
// return ((String) o1).compareTo((String) o2);
//按照字符串长度进行比较
return ((String) o1).length()-((String) o2).length();
}
});
treeMap.put("jack","杰克");
treeMap.put("tom","汤姆");
treeMap.put("kristina","克瑞斯提诺");
treeMap.put("smith","斯密斯");
System.out.println("treeMap="+treeMap);
/*
1.构造器把传入的比较器对象,赋给了 TreeSet 的底层的 TreeMap 的属性this.comparator
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
2.调用put方法
2.1 第一次添加 把 K V封装到 Entry 对象,放入 root
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
2.2 以后添加
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {//遍历所有的key 给当前的key 找到适当的位置
parent = t;
cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的compare
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else//如果遍历过程中,发现准备添加key 和当前已有的 Key 相等,就不添加
return t.setValue(value);
} while (t != null);
}
*/
}
}
TreeSet
该类实现了Set接口,可以实现排序等功能。
package com.hspedu.map_;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @author 山河与you皆无恙
*/
@SuppressWarnings({"all"})
public class TreeSet_ {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//return ((String)o2).compareTo((String)o1);
//按照长度大小比较
return ((String)o1).length()-((String)o2).length();
}
});
//添加数据
treeSet.add("jack");
treeSet.add("tom");
treeSet.add("sp");
treeSet.add("a");
treeSet.add("abc");//加入不了
System.out.println("treeSet="+treeSet);
/*
1.构造器把传入的比较器对象,赋给了 TreeSet 的底层的 TreeMap 的属性this.comparator
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
2.在调用 treeSet.add("tom"),会执行到
if (cpr != null) {//cpr就是我们的匿名内部类(对象)
do {
parent = t;
//动态绑定到我们的匿名内部类对象compare
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else//如果相等,即返回0,这个key就没有加入
return t.setValue(value);
} while (t != null);
}
*/
}
}
纸上得来终觉浅,绝知此事要躬行!
原文始发于微信公众号(itmkyuan):Java 集合框架
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/39471.html