java-day17

Day17-集合

1. Collection

1.1 概述
通过继承体系发现,集合中两大分类,List和Set 并且 两个都继承了Collection

那也就意味着,Collection中的方法是List和Set都有的,

所以我们先讲Collection,看看它里面都有什么方法

Collection 集合 只能存储单个元素,并且只能保存引用数据类型,不能保存基本数据类型

因为 底层就是 Object[] 数组,既然是Object 所以 即可以说 只能保存Object单一元素,也可以说
可以保存任何元素,因为Object是祖类,所有类型都会发生向上转型(多态)

基本类型真的不能存吗? 真的,因为基本类型和Object没有关系,但是 可以把基本类型转换为对应的包装类类型,而 包装类 是Object的子类,这样就能间接存储基本类型了

常用方法 :
boolean add() : 添加元素
void clear() : 清空集合
boolean remove() 删除某个元素
boolean isEmpty() 判断集合中是否为空
boolean contains() : 是否包含某个元素
int size() 返回集合中 元素个数

java集合是使程序能够存储和操纵元素不固定的一组数据。 所有Java集合类都位于java.uti包中。
【问】:之前我们需要把多个元素放到一起的时候,使用的是数组。那么为何还要提供Java集合工具类呢?
我们通过对比数组和Java集合工具类来解释Java集合工具类的必要性。
在这里插入图片描述

注意:如果集合中存放基本类型,一定要将其 “装箱”成对应的”基本类型包装类”。

1.2 继承体系
在这里插入图片描述
2. Map的继承层次结构
在这里插入图片描述
下面我们列举出最常用的几个子接口和实现类:
Collection ——> List ——> ArrayList类
Collection ——> List ——> LinkedList类
Collection ——> Set ——> HashSet类
Collection ——> Set ——> SortedSet接口 ——> TreeSet类
Map ——> HashMap类
Map ——> SortedMap ——> TreeMap类

1.3 Collection 和 lterator

1.3.1 Collection概述
Collection接口是List接口和Set接口的父接口,它定义的方法可以用于操作List集合和Set集合。
Collection接口定义的方法
在这里插入图片描述
1.3.2 Collection 使用

package com.demo._Collection;

import java.util.ArrayList;
import java.util.Collection;

/**
 * 通过继承体系发现,集合中两大分类,List和Set 并且 两个都继承了Collection
 * 
 * 那也就意味着,Collection中的方法是List和Set都有的,
 * 
 * 所以我们先讲Collection,看看它里面都有什么方法
 * 
 * Collection 集合 只能存储单个元素,并且只能保存引用数据类型,不能保存基本数据类型
 * 
 * 因为 底层就是 Object[] 数组,既然是Object 所以 即可以说 只能保存Object单一元素,也可以说
 * 可以保存任何元素,因为Object是祖类,所有类型都会发生向上转型(多态)
 * 
 * 基本类型真的不能存吗?  真的,因为基本类型和Object没有关系,但是 可以把基本类型转换为对应的包装类类型,而 包装类 是Object的子类,这样就能间接存储基本类型了
 * 
 * 常用方法 : 
 * 			boolean add() : 添加元素
 * 			void clear() : 清空集合
 * 			boolean remove() 删除某个元素
 * 			boolean isEmpty() 判断集合中是否为空
 * 			boolean contains() : 是否包含某个元素
 * 			int  size() 返回集合中 元素个数

 */
public class Collection_01 {
	public static void main(String[] args) {
		// 接口不能创建对象,所以我们以ArrayList为例,由于发生多态,所以丢失ArrayList的特有方法
		// 所以我们现在能够调用的方法都是Collection中的
		Collection c1 = new ArrayList();
		// 判断是否为空  true
		System.out.println(c1.isEmpty());//true
		
		// 添加
		c1.add("asd");
		// 123为int,会先自动装箱为 Integer,然后再向上转型为Object
		c1.add(123);
		
		Object  o1 = new Object();
		c1.add(o1);
		// false
		System.out.println(c1.isEmpty());//false
		// size不是数组的长度,而是数组中已经添加的元素个数
		for(Object temp:c1) {
			System.out.print(temp+" ");//asd 123 java.lang.Object@15db9742
			
		}
		System.out.println(c1.size());//2
		
		// 转数组
		Object[] arr = c1.toArray();
		for (Object object : arr) {
			System.out.println(object);
		}
		System.out.println("---------");
		// 删除
		c1.remove(123);
		// 重新获取数组
		arr = c1.toArray();
		for (Object object : arr) {
			System.out.println(object);
		}
		// 清空数组中元素
		c1.clear();
		System.out.println(c1.size());
	}
}

1.3.3 Iterator概述
在这里插入图片描述

Iterator是迭代器

迭代器是一种模式,它可以使序列类型的数据结构的遍历行为和被遍历的对象分离
也就是 我们无需关心该序列底层数据结构是什么样子的,只要拿到这个对象,使用迭代器就可以遍历这个对象的内部数据

创建迭代器对象
Iterator it = 集合对象.iterator();
调用集合对象自己的iterator方法就可以创建属于自己的迭代器

Iterator方法

1 boolean hasNext() : 判断光标下一位 是否还有元素,有就返回true,没有就返回false,
生成迭代器的时候,光标不是指向第一个元素的,而是在最顶端,没有指向任何元素
光标不会自动复位,使用完之后,必须重新生成

2 E next() : 把光标向下移动一位,并返回该位上的数据

3 remove() : 删除当前光标指向的元素
三个方法的使用顺序,就是 1,2,3

迭代器 一旦创建,如果集合中添加或者删除元素,那么迭代器必须重新重新生成,
否则调用next()方法会报错
但是 更改数据 不用重新生成

增强for循环,forEach 就是为了让用iterator循环访问的形式变简单,写起来方便,当然功能不太全,没有办法删除
所以需要有删除操作的话,还是要用原来的iterator形式

所以 forEach也是迭代器,使用forEach和使用iterator一样,不能添加或删除集合数据,但是更改可以

而 普通for和while这种遍历,都是和数据结构存储有关系的,比如数组 需要使用 arr[index]去访问
并且可以进行添加和删除操作

注意 使用迭代器进行遍历操作时 如果需要删除元素,只能使用 迭代器的remove方法,不能使用集合的remove方法

  1. Collection接口的iterator()和toArray()方法都用于获得集合中的所有元素,前者返回一个Iterator对象,后者返回一个包含集合中所有元素的数组。
  2. Iterator接口隐藏底层集合中的数据结构,提供遍历各种类型集合的统一接口。
    在这里插入图片描述
    1.3.4 lterator 使用
package com.demo._Collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * Iterator是迭代器
 * 
 * 迭代器是一种模式,它可以使序列类型的数据结构的遍历行为和被遍历的对象,分离
 * 		也就是 我们无需关心该序列底层数据结构是什么样子的,只要拿到这个对象,使用迭代器就可以遍历这个对象的内部数据
 * 
 * 创建迭代器对象
 * 		Iterator it = 集合对象.iterator();
 * 			调用集合对象自己的iterator方法就可以创建属于自己的迭代器
 * 
 * Iterator方法
 * 		1 boolean hasNext() : 判断光标下一位 是否还有元素,有就返回true,没有就返回false,
 * 				生成迭代器的时候,光标不是指向第一个元素的,而是在最顶端,没有指向任何元素
 * 				光标不会自动复位,使用完之后,必须重新生成
 * 		2 E next() : 把光标向下移动一位,并返回该位上的数据
 * 		3 remove() : 删除当前光标指向的元素
 * 		三个方法的使用顺序,就是 1,2,3 
 * 
 * 迭代器 一旦创建,如果集合中添加或者删除元素,那么迭代器必须重新重新生成,
 * 否则调用next()方法会报错
 * 	但是 更改数据 不用重新生成
 * 
 * 
 * 增强for循环,forEach 就是为了让用iterator循环访问的形式变简单,写起来方便,当然功能不太全,没有办法删除
 * 所以需要有删除操作的话,还是要用原来的iterator形式
 * 
 * 所以 forEach也是迭代器,使用forEach和使用iterator一样,不能添加或删除集合数据,但是更改可以
 * 
 * 而 普通for和while这种遍历,都是和数据结构存储有关系的,比如数组 需要使用 arr[index]去访问
 * 并且可以进行添加和删除操作
 * 
 * 注意 使用迭代器进行遍历操作时 如果需要删除元素,只能使用 迭代器的remove方法,不能使用集合的remove方法
 * 
 
 */
public class Collection_02_Iterator {

	public static void main(String[] args) {
		
	// 1 创建集合
		Collection c = new ArrayList();
		
		// 2 添加元素
		c.add(123);
		c.add("asd");
		c.add(2.3);
		c.add(false);
		c.add(null);
		
		// 创建迭代器
		Iterator it = c.iterator();
		// 判断还有没有元素,没有就终止
		//hasNext() Boolean型
		while(it.hasNext()){
			// 能进来说明有
			Object o = it.next();
			System.out.println(o);
		}
		System.out.println("===========");
		
		// false
		System.out.println(it.hasNext());
		
		// 使用for完成
		// 不会执行 因为 上面循环中 已经把光标移动到最后了
		// 当这里再判断 hasNext()的时候,就已经是false了
		for(;it.hasNext();){
			// 能进来说明有
			Object o = it.next();
			System.out.println(o);
		}
		
		// 如果此时 添加或者删除元素
		
		c.add(1);
		
		// 只要迭代器生成,集合添加或者删除,再使用这个迭代器 就会报错
		//  java.util.ConcurrentModificationException
		// 如果要使用,需要重新生成
		it=c.iterator();
		while(it.hasNext()){
			// 能进来说明有
			Object o = it.next();
			// 一旦生成迭代器 不能使用 集合的remove,除非重新生成,否则报错
//			c.remove(1);
			// 但是可以使用迭代器的remove进行删除操作
			it.remove();
			System.out.println(o);
		}
		// 0 循环删除完了
		System.out.println(c.size());
	}
}

1.3.5 注意:Contains 和 remove
boolean contains(Object o)
判断集合中是否包含某个元素

boolean remove(Object o)
在集合中删除指定元素

这两个方法,底层都会去调用equals方法进行比较
c.contains(“asd”) , 会用 asd 调用String的equals方法 挨个和集合中元素进行比较
判断谁,就用谁调用equals方法,和集合中元素进行比较
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

所以如果是存储的自定义类型(类对象),就需要根据需求覆写equals方法

package com.demo._Collection;

import java.util.ArrayList;
import java.util.Collection;

/**
 * boolean contains(Object o)
 * 		判断集合中是否包含某个元素
 * 
 * boolean remove(Object o)
 * 		在集合中删除指定元素
 * 
 * 这两个方法,底层都会去调用equals方法进行比较
 * 
 * 		比如 c.contains("asd") , 会用 asd 调用String的equals方法 挨个和集合中元素进行比较
 * 		同理 remove也是一样
 * 		判断谁,就用谁调用equals方法,和集合中元素进行比较
 * 
 * 所以如果是存储的自定义类型(类对象),就需要根据需求覆写equals方法
 * 
 */
public class Collection_03 {

	public static void main(String[] args) {
		// 1 创建集合
		Collection c = new ArrayList();
		Integer i1 = new Integer(1);
		Integer i2 = new Integer(2);
		Integer i3 = new Integer(3);
		c.add(i1);
		c.add(i2);
		c.add(i3);
		
		Integer i4 = new Integer(2);
		// false 因为new
		System.out.println(i4 == i2);
		// true 因为  Integer 重写了equals方法,比较的是值
		System.out.println(i4.equals(i2));
		// true,因为contains会自动调用 i4的equals方法和集合元素进行比较
		// 由于 i4是Integer类型,因为Integer覆写了equals方法,所以比较的是值
		System.out.println(c.contains(i4));
		
		Manager m1 = new Manager(2, "张三");
		Manager m2 = new Manager(2, "张三");
		c.add(m1);
		// true , 因为添加了m1,肯定是true
		System.out.println(c.contains(m1));
		// false,尽管m1和m2中数据一样,但是会调用equals方法,而Manager中没有覆写equals方法,
		// Object中的equals方法默认比较内存地址,m2和m1的内存地址不同,所以不存在
		System.out.println(c.contains(m2));
		
		// 需求 : 如果编号和姓名一致 就认为是同一个对象
		// 在Manager中覆写了equals方法之后,再比较 就是true了
		System.out.println(c.contains(m2));
	}
}

class Manager {
	private int no;
	private String name;

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

	@Override
	public boolean equals(Object obj) {
		System.out.println("=========");
		if (this == obj) {
			return true;
		}
		if (obj instanceof Manager) {
			Manager m2 = (Manager) obj;
			if (this.name.equals(m2.name) && this.no == m2.no) {
				return true;
			}
		}
		return false;
	}
	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Manager(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}

}

1.4 List
List元素的特性 : 有序可重复
存入顺序和取出顺序是一致的,并且有指定的下标可以表示数据的唯一性,所以可以存在重复数据

底层实现

ArrayList : 底层是数组,查询效率较高,添加和删除效率较低
LinkedList : 底层是双向链表,查询效率较低,添加和删除效率较高

Vector 已经过时了,ArrayList是Vector的升级版,而Vector属于线程安全,ArrayList属于非线程安全,所以ArrayList效率较高
在这里插入图片描述

package com.demo._Collection;

import java.util.ArrayList;
import java.util.List;

/**
 * List元素的特性 : 有序可重复
 * 		存入顺序和取出顺序是一致的,并且有指定的下标可以表示数据的唯一性,所以可以存在重复数据
 * 
 *   底层实现
 *   		ArrayList : 底层是数组,查询效率较高,添加和删除效率较低
 *   		LinkedList : 底层是双向链表,查询效率较低,添加和删除效率较高
 *   		Vector 已经过时了,ArrayList是Vector的升级版,而Vector属于线程安全,ArrayList属于非线程安全,所以ArrayList效率较高
 * 

 */
public class Collection_04_List {

	public static void main(String[] args) {
		List list = new ArrayList();
		list.add(2);
		list.add(3);
		// 输出 [2,3] ,因为输出引用的时候,会自动调用该对象的toString,而ArrayList覆写了
		System.out.println(list);
		
	}
}

1.4.1 ArrayList
深入List

ArrayList : 底层索引数组,下标0开始 初始化容量为 10 ,扩大容量为 原始容量的1.5倍.非线程安全,效率高

Vector : 初始化容量为10 , 扩大容量为 原始容量的 2 倍,线程安全,效率低

所以 Vector已经废弃

List遍历方式
while , for, foreach , iterator

常用方法

add(E e) : 将指定元素添加到尾部
add(int index,E e) : 将指定元素添加到指定位置,原位置内容统一向后移动
set(int index,E e) : 更改指定位置上的元素值
get(int index) : 获取指定索引上的元素
remove(int index) : 删除指定索引上的元素
remove(Object o) : 删除指定元素

package com.demo._Collection;

import java.util.ArrayList;
import java.util.List;

/**
 * 深入List
 * 
 * ArrayList : 底层索引数组,下标0开始 初始化容量为 10 ,扩大容量为 原始容量的1.5倍.非线程安全,效率高
 * 
 * Vector : 初始化容量为10 , 扩大容量为 原始容量的 2 倍,线程安全,效率低
 * 
 * 所以 Vector已经废弃
 * 
 * List遍历方式
 * 		while , for, foreach , iterator 
 * 
 * add(E e) : 将指定元素添加到尾部
 * add(int index,E e) : 将指定元素添加到指定位置,原位置内容统一向后移动
 * set(int index,E e) : 更改指定位置上的元素值
 * get(int index) : 获取指定索引上的元素
 * remove(int index) : 删除指定索引上的元素
 * remove(Object o) : 删除指定元素
 * 
 */
public class Collection_05_ArrayList {
	public static void main(String[] args)  {
		List li = new ArrayList();
		// 数组中 : 数组只能保存同一数据类型
		// 集合中 : 可以存储任意类型
		// 而ArrayList底层又是数组,很简单,因为ArrayList底层是Object[] 数组,  
		// 同理 我们单独声明Object[]数组的话,也可以说可以存储任意数据
		// 因为任何数据 都可以转型为Object类型,包括基本(自动装箱再向上转型)
		
		// 把数据添加到尾部
		li.add(1);
		// 把指定元素,插入到指定位置,该位置上的元素统一向后移动
		li.add(0, 2);
		System.out.println(li);
		// 更改指定位置上的元素
		li.set(0, 3);
		System.out.println(li);
		
		// 获取指定下标对应的数据
		Object o = li.get(1);
		System.out.println(o);
		
		// 删除 ,方法重载,如果 是 int 说明是要删除元素的下标是什么, Object 才是被删除的对象
		
		// 删除下标为3的元素
		// li.remove(3);
		// 删除元素值 为 Integer并且值为3的元素
		li.remove(new Integer(3));
		System.out.println(li);
		
		li.add("aa");
		li.add("aa2");
		li.add("aa3");
		for (Object object : li) {
			System.out.println(object);
		}
		System.out.println("----");
		for (int i = 0; i < li.size(); i++) {
			System.out.println(li.get(i));
		}
	}
}

1.4.2 LinkedList

1.4.2.1 基本使用
LinkedList : 底层是双向链表
链表 : 链表中保存的是节点,每个节点中有三个元素
1 自身对象(添加的元素) , 2 上一个节点的地址 , 3 下一个节点的地址
链表是没有下标的,内存空间也不是连续的,所以查询比较慢
由于内存空间不是连续的,只是保存上下节点的引用,随意添加删除比较快

add(E e) : 添加到尾部
push(E e) : 添加到头部
addFirst(E e) : 添加到头部
addLast(E e) : 添加到尾部
offerFirst(E e) 添加到头部,成功返回true
offerLast(E e) : 添加到尾部,成功返回true
get(int index) : 返回指定下标对应的数据(链表没有下标,只是模拟下标,方便我们查询使用)

本质 就调用了两个方法 : linkLast 和 linkFirst 所以没任何区别

底层实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.demo._Collection;

import java.util.LinkedList;

/**
 * LinkedList : 底层是双向链表
 * 		链表 : 链表中保存的是节点,每个节点中有三个元素
 * 			1 自身对象(添加的元素) , 2 上一个节点的地址 , 3 下一个节点的地址
 * 链表是没有下标的,内存空间也不是连续的,所以查询比较慢
 * 		由于内存空间不是连续的,只是保存上下节点的引用,随意添加删除比较快
 * 
 * add(E e) : 添加到尾部
 * push(E e) : 添加到头部
 * addFirst(E e) : 添加到头部
 * addLast(E e) : 添加到尾部
 * offerFirst(E e) 添加到头部,成功返回true
 * offerLast(E e) : 添加到尾部,成功返回true
 * get(int index) : 返回指定下标对应的数据(链表没有下标,只是模拟下标,方便我们查询使用)
 * 
 * 本质 就调用了两个方法 : linkLast 和 linkFirst 所以没任何区别
 */
public class Collection_06_LinkedList {
	public static void main(String[] args) {
		LinkedList linkedList = new LinkedList();
		linkedList.add(1);
		linkedList.addFirst(2);
		linkedList.addLast(3);
		linkedList.push(4);
		linkedList.offerFirst(5);
		linkedList.offerLast(6);
		// 遍历
		for (Object object : linkedList) {
			System.out.println(object);
		}
		System.out.println("----");
		for (int i = 0; i < linkedList.size(); i++) {
			System.out.println(linkedList.get(i));
		}
		
		// -------- 
		System.out.println("===");
		LinkedList linked = new LinkedList();
		linked.add("a");
		linked.add("b");
		linked.add("c");
		System.out.println(linked.size());
		System.out.println(linked.get(2));
		
	}
}

1.4.2.2 底层实现

1.4.2.2.1 Node节点类
双向链表
在这里插入图片描述
1.4.2.2.2 LinkedList类
在这里插入图片描述
而LinkedList中 保存了两个节点类的对象,分别是首节点和尾结点,方便我们使用,所以我们可以首部添加,也可以尾部添加
已添加为例,讲解LinkedList的底层实现
1.4.2.2.3 添加-add
在这里插入图片描述
在这里插入图片描述
根据add方法,最终发现实现尾部添加的是 linkLast方法
下一步 进行代码分析
在这里插入图片描述
1.4.2.2.4 获取-get
在这里插入图片描述
校验下标
在这里插入图片描述
在这里插入图片描述
获取数据
在这里插入图片描述
Get只是模拟下标获取的方式而已,其实本质就是遍历,从头挨个找
只不过做了一定的判断,判断是找前半截还是后半截,来决定 是正序遍历还是倒叙遍历
本质就是循环通过next一个一个的节点去找,所以这个get和ArrayList中的get完全不是一回事,ArrayList中就是封装了下标访问方式而已,下面是ArrayList的get方法实现
在这里插入图片描述
在这里插入图片描述
1.4.2.2.5 删除原理

循环找到要被删除的节点,比如说a节点
在这里插入图片描述
在这里插入图片描述

1.5 Set和排序
Set元素特点 : 无序不可重复

TreeSet : 底层红黑树
HashSet : 底层散列表

在这里插入图片描述

package com.demo._Collection;

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

/**
 * Set元素特点 : 无序不可重复
 * 
 *  TreeSet : 底层红黑树
 *  HashSet : 底层散列表
 * 
 */
public class Collection_07_Set {

	public static void main(String[] args) {
		Set s = new TreeSet();
		s.add(1);
		s.add(3);
		System.out.println(s.size());
		for (Object object : s) {
			System.out.println(object);
		}
	}
}

1.5.1 TreeSet
TreeSet : 元素必须有序,添加的元素会按照某种规则自动排序
想要使用TreeSet,元素必须要排序
数字 : 默认从小到大
字符串 : 默认比较每位ASCII码
日期 : 默认比较自然日期 昨天-今天-明天

package com.demo._Collection;

import java.util.TreeSet;

/**
 * TreeSet : 元素必须有序,添加的元素会按照某种规则自动排序
 * 想要使用TreeSet,元素必须要排序
 * 		数字 : 默认从小到大
 * 		字符串 : 默认比较每位ASCII码
 * 		日期 : 默认比较自然日期 昨天-今天-明天
 
 */
public class Collection_08_TreeSet {

	public static void main(String[] args) {
		TreeSet treeSet = new TreeSet();
		treeSet.add(1);
		treeSet.add(3);
		treeSet.add(2);
		treeSet.add(7);
		// 上面是数字,下面如果是字符串就会导致 报错,因为添加的时候需要比较元素大小
		// 而不同类型 是没有可比性的
		// treeSet.add("a");
		for (Object object : treeSet) {
			System.out.println(object);
		}
		System.out.println("----");
		TreeSet treeSet2 = new TreeSet();
		treeSet2.add("a");
		treeSet2.add("1");
		// 如果有多个字符,先比较第一位,如果第一位不同,则第一位小的在上面
		// 如果第一位相同,再比较第二位,以此类推
		treeSet2.add("11");//把11拆开1 1先比较第一个1,再比较第二个1
		treeSet2.add("101");
		treeSet2.add("b");
		treeSet2.add("n");
		for (Object object : treeSet2) {
			System.out.println(object);
		}
	}
}

1.5.2 排序
1.5.2.1 Comparable

比较器有两种 : 1 元素自身比较器, 2 比较器类

思考 : 为什么字符串,Integer,Date可以排序?
因为都实现了 implements Comparable

因为使用treeSet在进行数据添加的时候,会自动调用该对象的compareTo()方法和集合内元素进行比较

如果我们想要存储自定义类型怎么办?
需要实现该接口才行

在这里插入图片描述

添加的时候 会自动调用该对象的compareTo方法,而该方法就在Comparable接口中,所以 必须要实现,否则不能添加到TreeSet中

在这里插入图片描述

package com.demo._Collection;

import java.util.TreeSet;

/**
 * 比较器有两种 : 1 元素自身比较器, 2 比较器类
 * 
 * 思考 : 为什么字符串,Integer,Date可以排序?
 * 		因为都实现了 implements Comparable 
 * 
 * 因为使用treeSet在进行数据添加的时候,会自动调用该对象的compareTo()方法和集合内元素进行比较
 * 
 * 如果我们想要存储自定义类型怎么办?
 * 		需要实现该接口才行
 * 
 * @author 天亮教育-帅气多汁你泽哥
 * @Date 2021年1月22日
 */
public class Collection_09_TreeSet {
	public static void main(String[] args) {
		TreeSet treeSet = new TreeSet();
		User user1 = new User(11);
		User user2 = new User(13);
		User user3 = new User(6);
		treeSet.add(user1);
		treeSet.add(user2);
		treeSet.add(user3);
		System.out.println(treeSet.size());
		
		for (Object object : treeSet) {
			System.out.println(object);
		}
	}
}

class User implements Comparable{
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public User(int age) {
		super();
		this.age = age;
	}

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

	@Override
	public int compareTo(Object o) {
		// this 是当前对象
		// o 是集合内对象
		// 并且 返回值为0 表示 相等,则不添加
		// 返回大于0 的 表示 要添加的元素大,则放到后面
		// 返回小于0 的 表示 要添加的元素小,则放到前面

		User user = (User) o;
		// 升序
//		return this.age - user.age;
		// 降序
		 return user.age - this.age;
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值