1. 集合的理解和好处
- 数组
- 集合
2. 集合的框架体系
Java 的集合类很多,主要分为两大类
- 单列集合
- 双列集合
//1. 集合主要是两组(单列集合 , 双列集合)
//2. Collection 接口有两个重要的子接口 List Set , 他们的实现子类都是单列集合
//3. Map 接口的实现子类 是双列集合,存放的 K-V
//Collection
ArrayList arrayList = new ArrayList();
arrayList.add("jack");
arrayList.add("tom");
//Map
HashMap hashMap = new HashMap();
hashMap.put("NO1", "北京");
hashMap.put("NO2", "上海");
3. Collection 接口和常用方法
Collection 接口实现类的特点
List list = new ArrayList();
// add:添加单个元素
list.add("jack");
list.add(10);//相当于 list.add(new Integer(10));
list.add(true);
System.out.println("list=" + list);//list=[jack, 10, true]
// remove:删除指定元素
list.remove(0);//删除第一个元素
list.remove(true);//指定删除某个元素
System.out.println("list=" + list);//list=[10]
// contains:查找元素是否存在
System.out.println(list.contains("jack"));//F
// size:获取元素个数
System.out.println(list.size());//1
// isEmpty:判断是否为空
System.out.println(list.isEmpty());//F
// clear:清空
list.clear();
System.out.println("list=" + list);//list=[]
// addAll: 添 加 多 个 元 素
ArrayList list2 = new ArrayList();
list2.add("红楼梦");
list2.add("三国演义");
list.addAll(list2);
System.out.println("list=" + list);//list=[红楼梦, 三 国 演 义 ]
// containsAll:查找多个元素是否都存在
System.out.println(list.containsAll(list2));//T
// removeAll:删除多个元素
list.add("聊斋");
list.removeAll(list2);
System.out.println("list=" + list);//list=[聊斋]
// 说明:以 ArrayList 实现类来演示.
Collection 接口遍历元素方式 1-使用Iterator(迭代器)
迭代器的使用案例
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new Book("三国演义", "罗贯中", 10.1));
col.add(new Book("小李飞刀", "古龙", 5.1));
col.add(new Book("红楼梦", "曹雪芹", 34.6));
System.out.println("col=" + col);//col=[Book{name='三国演义', author='罗贯中', price=10.1}, Book{name='小李飞刀', author='古龙', price=5.1}, Book{name='红楼梦', author='曹雪芹', price=34.6}]
//现在老师希望能够遍历 col 集合
//1. 先得到 col 对应的 迭代器
Iterator iterator = col.iterator();
//2. 使用 while 循环遍历
//快捷键,快速生成 while => itit
//显示所有的快捷键的的快捷键 ctrl + j
while (iterator.hasNext()) {//判断是否还有数据
//返回下一个元素,类型是 Object
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
//3.当退出 while 循环后,这时iterator迭代器,指向最后的元素
// iterator.next();//抛出异常 NoSuchElementException
//4. 如果希望再次遍历,需要重置我们的迭代器
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 +
'}';
}
}
Collection 接口遍历对象方式 2-for 循环增强
- 练习
public static void main(String[] args) {
List list = new ArrayList();
list.add(new Dog("小黑", 3));
list.add(new Dog("大黄", 100));
list.add(new Dog("大壮", 8));
//先使用 for 增强
for (Object dog : list) {
System.out.println("dog=" + dog);
}//dog=Dog{name='小黑', age=3}
//dog=Dog{name='大黄', age=100}
//dog=Dog{name='大壮', age=8}
//增强for,也可以直接在数组中使用
int[] nums = { 1, 8, 10, 33};
for (int i : nums){
System.out.println("i="+i);
}//i=1 i=8 i=10 i=33
//使用迭代器
System.out.println("===使用迭代器来遍历===");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object dog = iterator.next();
System.out.println("dog=" + dog);
}//dog=Dog{name='小黑', age=3}
//dog=Dog{name='大黄', age=100}
//dog=Dog{name='大壮', age=8}
}
/**
*创建3个Dog{name, age}对象,放入到 ArrayList 中,赋给 List 引用
*用迭代器和增强 for 循环两种方式来遍历
*重写 Dog 的 toString 方法, 输出 name 和 age
*/
class Dog {
private String name;
private int age;
public Dog(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 "Dog{" +"name='" + name + '\'' + ", age=" + age + '}';}
4. List 接口和常用方法
List 接口基本介绍
public static void main(String[] args) {
//1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复 [案例]
List list = new ArrayList();
list.add("jack");
list.add("tom");
list.add("mary");
list.add("hsp");
list.add("tom");
System.out.println("list=" + list);//list=[jack, tom, mary, hsp, tom]
//2. List 集合中的每个元素都有其对应的顺序索引,即支持索引
// 索引是从 0 开始的
System.out.println(list.get(3));//hsp
}
List 接口的常用方法
public static void main(String[] args) {
List list = new ArrayList();
list.add("张三丰");
list.add("贾宝玉");
// void add(int index, Object ele):
// 在 index 位置插入 ele 元素
//在 index = 1 的位置插入一个对象
list.add(1, "张三");
System.out.println("list=" + list);//list=[张三丰, 张三, 贾宝玉]
//boolean addAll(int index, Collection eles);//从 index 位置开始将 eles 中的所有元素添加进来
List list2 = new ArrayList();
list2.add("jack");
list2.add("tom");
list.addAll(1, list2);
System.out.println("list=" + list);//list=[张三丰, jack, tom, 张三, 贾宝玉]
// Object get(int index):获取指定 index 位置的元素
// int indexOf(Object obj):返回 obj 在集合中首次出现的位置
System.out.println(list.indexOf("tom"));//2
// int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置
list.add("张三");
System.out.println("list=" + list);//list=[张三丰, jack, tom, 张三, 贾宝玉, 张三]
System.out.println(list.lastIndexOf("张三"));//5
// Object remove(int index):移除指定 index 位置的元素,并返回此元素
list.remove(0);
System.out.println("list=" + list);//list=[jack, tom, 张三, 贾宝玉, 张三]
// Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换.
list.set(1, " 玛 丽 ");
System.out.println("list=" + list);//list=[jack, 玛 丽 , 张三, 贾宝玉, 张三]
// List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
// 注意返回的子集合 fromIndex <= subList < toIndex
List returnlist = list.subList(0, 2);
System.out.println("returnlist=" + returnlist);//returnlist=[jack, 玛 丽 ]
}
List 接口练习
/**
添加 10 个以上的元素(比如 String "hello" ),在 2 号位插入一个元素"Java学习",
获得第 5 个元素,删除第 6 个元素,修改第 7 个元素,在使用迭代器遍历集合,
要求:使用 List 的实现类 ArrayList 完成。
*/
public static void main(String[] args) {
List list = new ArrayList();
for (int i = 0; i < 12; i++) {
list.add("hello" + i);
}
System.out.println("list=" + list);
//在 2 号位插入一个元素"Java学习"
list.add(1, "Java学习");
System.out.println("list=" + list);
//获得第 5 个元素
System.out.println("第五个元素=" + list.get(4));
//删除第 6 个元素list.remove(5);
System.out.println("list=" + list);
//修改第 7 个元素
list.set(6, " 三 国 演 义 ");
System.out.println("list=" + list);
//在使用迭代器遍历集合
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
}
List 的三种遍历方式 [ArrayList, LinkedList,Vector]
public static void main(String[] args) {
//List 接口的实现子类 Vector LinkedList
//List list = new ArrayList();
//List list = new Vector();
List list = new LinkedList();
list.add("jack");
list.add("tom");
list.add("鱼香肉丝");
list.add("北京烤鸭子");
//遍历
//1. 迭代器iterator
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
System.out.println("=====增强 for=====");//jack tom 鱼香肉丝 北京烤鸭子
//2. 增强 for
for (Object o : list) {
System.out.println("o=" + o);
}
System.out.println("=====普通 for====");//o=jack o=tom o=香肉丝 o=北京烤鸭子
//3. 使用普通 for
for (int i = 0; i < list.size(); i++) {
System.out.println("对象=" + list.get(i));
}//对象=jack 对象=tom 对象=鱼香肉丝 对象=北京烤鸭子
}
实现类的练习 2
public static void main(String[] args) {
List list = new ArrayList();
// List list = new LinkedList();
// List list = new Vector();
list.add(new Book("红楼梦", "曹雪芹", 100));
list.add(new Book("西游记", "吴承恩", 10));
list.add(new Book("水浒传", "施耐庵", 19));
list.add(new Book("三国演义", "罗贯中", 80));
//如何对集合进行排序
//遍历
for (Object o : list) {
System.out.println(o);
}
//冒泡排序
sort(list);
System.out.println("==排序后==");
for (Object o : list) {
System.out.println(o);
}
/**==排序后==
名称:西游记 价格:10.0 作者:吴承恩
名称:水浒传 价格:19.0 作者:施耐庵
名称:三国演义 价格:80.0 作者:罗贯中
名称:红楼梦 价格:100.0 作者:曹雪芹
*/
}
//静态方法
//价格要求是从小到大
public static void sort(List list) {
int listSize = list.size();
for (int i = 0; i < listSize - 1; i++) {
for (int j = 0; j < listSize - 1 - i; j++) {
//取出对象 Book
Book book1 = (Book) list.get(j);
Book book2 = (Book) list.get(j + 1);
if (book1.getPrice() > book2.getPrice()) {//交换
list.set(j, book2);
list.set(j + 1, book1);
}
}
}
}
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 "名称:" + name + "\t\t价格:" + price + "\t\t作者:" + author; }
}
5. ArrayList 底层结构和源码分析
ArrayList 的注意事项
//ArrayList 是线程不安全的, 可以看源码 没有 synchronized 关键字修饰
/*
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
*/
ArrayList arrayList = new ArrayList();
arrayList.add(null);
arrayList.add("jack");
arrayList.add(null);
arrayList.add("hsp");
System.out.println(arrayList);//[null, jack, null, hsp]
ArrayList 的底层操作机制源码分析(重点,难点.)
/* 2 */
//使用无参构造器创建 ArrayList 对象
// ArrayList list = new ArrayList();
ArrayList list = new ArrayList(8);
//使用 for 给 list 集合添加 1-10 数据
for (int i = 1; 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);
6. Vector 底层结构和源码剖析
- Vector 的基本介绍
//无参构造器
//有参数的构造
Vector vector = new Vector(8);
for (int i = 0; i < 10; i++) {
vector.add(i);
}
vector.add(100);
System.out.println("vector=" + vector);
//解读源码
//1. new Vector() 底层
/*
public Vector() { this(10);
}
补充:如果是 Vector vector = new Vector(8);
走的方法:
public Vector(int initialCapacity) { this(initialCapacity, 0);
}
2.vector.add(i)
2.1//下面这个方法就添加数据到 vector 集合
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e;
return true;
}
2.2//确定是否需要扩容 条件 : minCapacity - elementData.length>0 private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
2.3 //如果 需要的数组大小 不够用,就扩容 , 扩容的算法
//newCapacity = oldCapacity + ((capacityIncrement > 0) ?
// capacityIncrement : oldCapacity);
//就是扩容两倍.
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);
}
*/
Vector 和ArrayList 的比较
7. LinkedList 底层结构
LinkedList 的全面说明
LinkedList 的底层操作机制
8. ArrayList 和 LinkedList 比较
9. Set 接口和常用方法
Set 接口基本介绍
Set 接口的常用方法
- 和 List 接口一样, Set 接口也是 Collection 的子接口,因此,常用方法和 Collection 接口一样.
Set 接口的遍历方式
Set 接口的常用方法举例
//1. 以 Set 接口的实现类 HashSet 来讲解 Set 接口的方法
//2. set 接口的实现类的对象(Set 接口对象), 不能存放重复的元素, 可以添加一个 null
//3. set 接口对象存放数据是无序(即添加的顺序和取出的顺序不一致)
//4. 注意:取出的顺序的顺序虽然不是添加的顺序,但是取出顺序是固定的.
Set set = new HashSet();
set.add("john");
set.add("lucy");
set.add("john");//重复set.add("jack");
set.add("hsp");
set.add("mary");
set.add(null);//
set.add(null);//再次添加 null
for (int i = 0; i < 10; i++) {
System.out.println("set=" + set);
}//循环输出,表明添加的顺序和取出的顺序不一致,但取出顺序是固定的
//遍历
//方式 1: 使用迭代器
System.out.println("=====使用迭代器====");
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println("obj=" + obj);
}
set.remove(null);//删除内容
//方式 2: 增强 for
System.out.println("=====增强 for====");
for (Object o : set) {
System.out.println("o=" + o);
}
//set 接口对象,不能通过索引来获取
10. Set 接口实现类-HashSe(不懂,未掌握)
HashSet 的全面说明
//1. 构造器走的源码
/*
public HashSet() {
map = new HashMap<>();
}
2. HashSet 可以存放 null, 但是只能有一个 null, 即元素不能重复
*/
Set hashSet = new HashSet();
hashSet.add(null);
hashSet.add(null);
System.out.println("hashSet=" + hashSet);
HashSet 案例说明
public static void main(String[] args) {
HashSet set = new HashSet();
//说明
//1. 在执行 add 方法后,会返回一个 boolean 值
//2. 如果添加成功,返回 true, 否则返回 false
//3. 可以通过 remove 指定删除哪个对象
System.out.println(set.add("john"));//T
System.out.println(set.add("lucy"));//T
System.out.println(set.add("john"));//F
System.out.println(set.add("jack"));//T
System.out.println(set.add("Rose"));//T
set.remove("john");
System.out.println("set=" + set);//3 个 set=[Rose, lucy, jack]
set = new HashSet();//重置
System.out.println("set=" + set);//0 set=[]
//4 Hashset 不能添加相同的元素/数据?
set.add("lucy");//添加成功
set.add("lucy");//加入不了
set.add(new Dog("tom"));//OK
set.add(new Dog("tom"));//Ok
System.out.println("set=" + set);//et=[Dog{name='tom'}, lucy, Dog{name='tom'}]
//在加深一下. 非常经典的面试题.
//看源码,做分析, 先给留一个坑,以后讲完源码,就了然
//去看他的源码,即 add 到底发生了什么?=> 底层机制.
set.add(new String("hsp"));//ok
set.add(new String("hsp"));//加入不了.
System.out.println("set=" + set);//set=[hsp, Dog{name='tom'}, lucy, Dog{name='tom'}]
}
class Dog { //定义了 Dog 类
private String name;
public Dog(String name) { this.name = name; }
@Override
public String toString() {
return "Dog{" + "name='" + name + '\'' + '}';
}
}
HashSet 底层机制说明
HashSet 练习
public static void main(String[] args) {
/**
定义一个 Employee 类,该类包含:private 成员属性 name,age
要求: 创建 3 个 Employee 对象放入 HashSet 中
当name和age的值相同时,认为是相同员工,不能添加到HashSet集合中
*/
HashSet hashSet = new HashSet();
hashSet.add(new Employee("milan", 18));//ok
hashSet.add(new Employee("smith", 28));//ok
hashSet.add(new Employee("milan", 18));//加入不成功.
//回答,加入了几个? 3 个hashSet=[Employee{name='milan', age=18},Employee{name='smith', age=28}, Employee{name='milan', age=18}]
System.out.println("hashSet=" + hashSet);
}//hashSet=[Employee{name='smith', age=28}, Employee{name='milan', age=18}]
//创建 Employee
class Employee {
private String name;
private int age;
public Employee(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; }
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void setAge(int age) { this.age = age; }
//如果 name 和 age 值相同,则返回相同的 hash 值
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return age == employee.age &&
Objects.equals(name, employee.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
11. Set 接口实现类-LinkedHashSet(不懂,未掌握)
LinkedHashSet 的全面说明
LinkedHashSet 练习
public static void main(String[] args) {
LinkedHashSet linkedHashSet = new LinkedHashSet();
linkedHashSet.add(new Car(" 奥 拓 ", 1000));//OK
linkedHashSet.add(new Car(" 奥 迪 ", 300000));//OK
linkedHashSet.add(new Car("法拉利", 10000000));//OK
linkedHashSet.add(new Car("奥迪", 300000));//加入不了
linkedHashSet.add(new Car("保时捷", 70000000));//OK
linkedHashSet.add(new Car("奥迪", 300000));//加入不了
System.out.println("linkedHashSet=" + linkedHashSet);
}//linkedHashSet=[
// Car{name=' 奥 拓 ', price=1000.0},
// Car{name=' 奥 迪 ', price=300000.0},
// Car{name='法拉利', price=1.0E7},
// Car{name='奥迪', price=300000.0},
// Car{name='保时捷', price=7.0E7}]
/**
* Car 类(属性:name,price), 如果 name 和 price 一样,
* 则认为是相同元素,就不能添加。 5min
*/
class Car {
private String name;
private double price;
public Car(String name, double price) {
this.name = name;
this.price = price;
}
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; }
@Override
public String toString() {
return "\nCar{" +
"name='" + name + '\'' + ", price=" + price +
'}';
}
//重写 equals 方法 和 hashCode
//当 name 和 price 相同时, 就返回相同的 hashCode 值, equals 返回 t
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return Double.compare(car.price, price) == 0 && Objects.equals(name, car.name);
}
@Override
public int hashCode() {
return Objects.hash(name, price);
}
}
12. Map 接口和常用方法(不懂,未掌握)
Map 接口实现类的特点 [很实用]
Map 接口常用方法
Map 接口遍历方法
Map 接口实现类-HashMap(不懂,未掌握)
HashMap 小结
HashMap 底层机制及源码剖析
HashMap 底层机制及源码剖析
14. Map 接口实现类-Hashtable(不懂,未掌握)
HashTable 的基本介绍
Hashtable 和 HashMap 对比
15. Map 接口实现类-Properties(不懂,未掌握)
基本介绍
基本使用
16. 总结-开发中如何选择集合实现类(记住)
TreeSet源码解读
public static void main(String[] args) {
//1. 当我们使用无参构造器,创建 TreeSet 时,仍然是无序的
//2. 老师希望添加的元素,按照字符串大小来排序
//3. 使用 TreeSet 提供的一个构造器,可以传入一个比较器(匿名内部类)
// 并指定排序规则
//4. 简单看看源码
/*
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);
}
*/
// TreeSet treeSet = new TreeSet();
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//下面 调用 String 的 compareTo 方法进行字符串大小比较
//如果老韩要求加入的元素,按照长度大小排序
//return ((String) o2).compareTo((String) o1);
return ((String) o1).length() - ((String) o2).length();
}
});
// 添 加 数 据 .
treeSet.add("jack");
treeSet.add("tom");//3
treeSet.add("sp");
treeSet.add("a");
treeSet.add("abc");//3
System.out.println("treeSet=" + treeSet);
}//treeSet=[a, sp, tom, jack]
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) 的大小进行排序
//按照 K(String) 的长度大小排序
//return ((String) o2).compareTo((String) o1);
return ((String) o2).length() - ((String) o1).length();
}
});
treeMap.put("jack", "杰克");
treeMap.put("tom", "汤姆");
treeMap.put("kristina", "克瑞斯提诺");
treeMap.put("smith", "斯密斯");
treeMap.put("zs", "张三");//加入不了
System.out.println("treemap=" + treeMap);
//treemap={kristina=克瑞斯提诺, smith=斯密斯, jack=杰克, tom=汤姆, zs=张三}
/*
解读源码:
1.构造器. 把传入的实现了 Comparator 接口的匿名内部类(对象),传给给 TreeMap 的 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);
}
*/
17. Collections 工具类
Collections 工具类介绍
排序操作:(均为static 方法)
public static void main(String[] args) {
//创建ArrayList 集合,用于测试.
List list = new ArrayList();
list.add("tom");
list.add("smith");
list.add("king");
list.add("milan");
list.add("tom");
//reverse(List):反转 List 中元素的顺序
Collections.reverse(list);
System.out.println("list=" + list);//list=[tom, milan, king, smith, tom]
//shuffle(List):对 List 集合元素进行随机排序
// for (int i = 0; i < 5; i++) {
Collections.shuffle(list);
System.out.println("list=" + list);//list=[milan, tom, tom, king, smith]
// }
//sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
Collections.sort(list);
System.out.println("自然排序后");
System.out.println("list=" + list);//list=[king, milan, smith, tom, tom]
//sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
//我们希望按照 字符串的长度大小排序
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//可以加入校验代码.
return ((String) o2).length() - ((String) o1).length();
}
});
System.out.println("字符串长度大小排序=" + list);//字符串长度大小排序=[milan, smith, king, tom, tom]
//swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
//比如
Collections.swap(list, 0, 1);
System.out.println("交换后的情况");
System.out.println("list=" + list);//list=[smith, milan, king, tom, tom]
//Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
System.out.println("自然顺序最大元素=" + Collections.max(list));//自然顺序最大元素=tom
//Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
//比如,我们要返回长度最大的元素
Object maxObject = Collections.max(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((String)o1).length() - ((String)o2).length();//返回最小 o1与o2互换
}
});
System.out.println("长度最大的元素=" + maxObject);//长度最大的元素=smith
//Object min(Collection)
//Object min(Collection,Comparator)
//上面的两个方法,参考max即可
//int frequency(Collection,Object):返回指定集合中指定元素的出现次数
System.out.println("tom出现的次数=" + Collections.frequency(list, "tom"));//tom出现的次数=2
//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);//dest=[smith, milan, king, tom, tom]
//boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
//如果list中,有tom 就替换成 汤姆
Collections.replaceAll(list, "tom", "汤姆");
System.out.println("list替换后=" + list);//list替换后=[smith, milan, king, 汤姆, 汤姆]
}