1.3 Set接口
Set集合 作为Collection另一子类,是一种不允许重复但不保证输出顺序的集合
子类一:HashSet()
HashSet 底层是通过HashMap实现的,HashMap的底层是哈希表结构
语法实例
public static void method() {
Set set = new HashSet();
set.add("东北平原");
set.add("华北平原");
set.add("长江中下游平原");
set.add("关中平原");
set.add("华北平原");
System.out.println(set);
}
Collection的其他常用方法同样可以在Set中使用,不做演示
关于set集合如何实现不重复,参见我的这篇博客:
子类二:TreeSet()
TreeSet 底层是TreeMap来实现的,TreeMap的底层是红黑树数据结构
二叉树:小的在左边,大的在右边
TreeSet对于基本数据包装类和字符串采取的默认的自然排序法
public static void method() {
Set set = new TreeSet();
set.add(14);
set.add(7);
set.add(27);
set.add(44);
System.out.println(set);//[7, 14, 27, 44]
Set set2 = new TreeSet();
set2.add("abc");
set2.add("bdd");
set2.add("caa");
set2.add("acc");
System.out.println(set2);//[abc, acc, bdd, caa]
}
对于引用数据类型,没法直接排,对象里的属性不能作为直接的排序的依据
所以我们
- 需要实现Comparable接口,然后重写compareTo方法,用于用户自定义排序方式
public static void objMethod() {
Set set = new TreeSet();//里面的默认构造器是自然排序法,我们将自定义的放进去
set.add(new User(17,"小李"));
set.add(new User(23,"小张"));
set.add(new User(15,"小孙"));
set.add(new User(23,"小陈"));
System.out.println(set);
}
class User implements Comparable{ //实现Comparable接口
private int age;
private String name;
public User() {
}
public User(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
/**
* 用于用户自定义排序方式
* 拿两个对象的年龄进行比较
* >排左边 <排右边 0相等
*/
@Override
public int compareTo(Object obj) {
User user = (User)obj; //进行类型转换
int temp=this.age - user.age;
if(temp==0) {//先比较年龄,再比较名字,如果不等于0,直接返回结果
//比较名字
return this.name.compareTo(user.name);
}
return temp;
}
输出结果
[User [age=15, name=小孙], User [age=17, name=小李], User [age=23, name=小张], User [age=23, name=小陈]]
- 但是Comparable的坏处是,没法定义多个compareTo方法以适应不同的比较规则
- 这个时候我们用到了 Comparator 接口
- TreeSet(Comparator<? super E> comparator) 构造一个新的,空的树集,根据指定的比较器进行排序。
/**
* 比较器实例
* 实体类来自Item,比较器来自CompareByPriceAndBrand
*
*/
public static void customObjMethod() {
Set set = new TreeSet(new CompareByPriceAndBrand());
//里面的默认构造器是自然排序法,我们将自定义的放进去
set.add(new Item(9.9,"锅巴","bbc"));
set.add(new Item(24.8,"夏威夷果","三只松鼠"));
set.add(new Item(18.9,"猪肉脯","良品铺子"));
set.add(new Item(9.9,"酸奶","aac"));
System.out.println(set);
}
public class CompareByPriceAndBrand implements Comparator{
@Override
public int compare(Object o1, Object o2) {//o1和o2是两个比较对象
Item item1 = (Item)o1;
Item item2 = (Item)o2;
//先比较价格
double temp = item1.getPrice() - item2.getPrice();
//判断价格是否相等,如果相等就根据商家的品牌名进行排序
if(temp == 0) {
return item1.getBrand().compareTo(item2.getBrand());
}
return (int)temp;
}
}
输出结果
[Items [price=9.9, name=酸奶, brand=aac], Items [price=9.9, name=锅巴, brand=zbc], Items [price=18.9, name=猪肉脯, brand=良品铺子], Items [price=24.8, name=夏威夷果, brand=三只松鼠]]
2. 双列集合
Map集合是双列集合,是以键值对的形式存储数据的,既一对一的映射关系
Map集合中key值不能重复的,同时,key所对应的值至多为一个。
但是值是可以重复的,重复的两个值对应不同的key
- 添加方法
/**
* 添加方法
*/
public static void putMethod() {
Map map = new HashMap();
map.put("name","锅巴");
map.put("price",10);
map.put("brand","好趣味");
System.out.println("map--"+map);
map.put("price",20);
System.out.println("map添加后--"+map);
//key值相同的情况下,会进行值的覆盖
map.put(null,null);
System.out.println("map空值实例--"+map);
//如何存自定义类型
Map map2 = new HashMap();
Item item = new Item("夏威夷果","三只松鼠",18.9);
map2.put(item, 1);
map2.put(2, new Item("腰果","百草味",25.9));
System.out.println("map2"+map2);
map.putAll(map2);
System.out.println("移除交集后--"+map);
}
结果:
map--{price=10, name=锅巴, brand=好趣味}
map添加后--{price=20, name=锅巴, brand=好趣味}
map空值实例--{null=null, price=20, name=锅巴, brand=好趣味}
map2{2=Item [name=腰果, brand=百草味, price=25.9], Item [name=夏威夷果, brand=三只松鼠, price=18.9]=1}
移除交集后--{null=null, 2=Item [name=腰果, brand=百草味, price=25.9], price=20, name=锅巴, brand=好趣味, Item [name=夏威夷果, brand=三只松鼠, price=18.9]=1}
- 移除方法
public static void removeMethod() {
Map map = new HashMap();
map.put("name","锅巴");
map.put("price",10);
map.put("brand","好趣味");
System.out.println("map--"+map);
map.remove("brand");
System.out.println("map删--"+map);
map.remove("name","烧饼");//要是想删键和对应的值,就要都写对
System.out.println("map删2--"+map);
map.remove("price",10);
System.out.println(map);
map.clear();//清空集合
System.out.println(map);
System.out.println(map.size());//集合内元素数量
}
结果:
map--{price=10, name=锅巴, brand=好趣味}
map删--{price=10, name=锅巴}
map删2--{price=10, name=锅巴}
{name=锅巴}
{}
0
- 获取方法
/**
* 获取方法
*/
public static void getMethod(){
Map map = new HashMap();
map.put("name","锅巴");
map.put("price",10);
map.put("brand","好趣味");
System.out.println(map.get("brand"));
}
结果:
好趣味
- 如何进行遍历
三种方法,collection,keySet(),和entrySet()
- values 以Collection的形式进行遍历
public static void ergodicMethod() {
Map map = new HashMap();
map.put("name","锅巴");
map.put("price",10);
map.put("brand","好趣味");
Collection coll = map.values();
Iterator it = coll.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
- keySet() 将所有的key封装成一个Set集合进行遍历
- Map集合中要求key是不能重复的,而Set集合本身就是不重复的
public static void ergodicMethod2() {
Map map = new HashMap();
map.put("name","锅巴");
map.put("price",10);
map.put("brand","好趣味");
Set set = map.keySet();
Iterator it = set.iterator();
while (it.hasNext()) {
Object key = it.next();
Object value = map.get(key);
System.out.println("key为"+key+" "+"value值为"+value);
}
}
- entrySet() 将整个映射作为一个整体进行使用,返回值类型Set<Map.Entry> Map.Entry是Map集合中的一个内部接口
public static void ergodicMethod3() {
Map map = new HashMap();
map.put("name", "锅巴");
map.put("price", 10);
map.put("brand", "好趣味");
Set set = map.entrySet();
// 迭代器中存储的整个键对值关系 ---- Entry 因为是一个内部接口, 将map整体封装进去Entry,再写上setget方法来获取key和value
Iterator it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println("key为" + key + " " + "value值为" + value);
}
}
- TreeMap的排序 (基于key来进行自然排序)
public static void orderMethod() {
Map map = new TreeMap();
map.put("name", "锅巴");
map.put("price", 10);
map.put("brand", "好趣味");
System.out.println(map);
//基于比较器的自定义类型排序
Map map2 = new TreeMap(new CompareByPriceAndBrand());
map2.put(new Item("夏威夷果", "sanzhisongshu", 9.9), "自定义类型1");
map2.put(new Item("腰果", "liangpinpuzi", 12.3), "自定义类型2");
map2.put(new Item("碧根果", "baicaowei", 9.9), "自定义类型3");
System.out.println(map2);
}
class CompareByPriceAndBrand implements Comparator{
@Override
public int compare(Object o1, Object o2) {//o1和o2是两个比较对象
Item item1 = (Item)o1;
Item item2 = (Item)o2;
//先比较价格
double temp = item1.getPrice() - item2.getPrice();
//判断价格是否相等,如果相等就根据商家的品牌名进行排序
if(temp == 0) {
return item1.getBrand().compareTo(item2.getBrand());
}
return (int)temp;
}
}
结果
{brand=好趣味, name=锅巴, price=10}
{Item [name=碧根果, brand=baicaowei, price=9.9]=自定义类型3, Item [name=夏威夷果, brand=sanzhisongshu, price=9.9]=自定义类型1, Item [name=腰果, brand=liangpinpuzi, price=12.3]=自定义类型2}