集合框架

包括一系列的接口和类 存放集合数据

接口继承关系图

接口继承关系.jpg

Collection接口 父接口,提供ListSet等共同的一些方法,例如:addremovecleariteratorsize

Set接口 包含一组不重复的数据,Set中数据是无序的,没有下标

List接口 包含一组有序的数组,List中的数据都是有下标的,可以包含重复的数据

Queue接口 ”先进先出“

Deque接口 ”双端队列“

Map接口 “键值对” K-V key就是键 value就是值(数据)

实现

Set接口:

(1)HashSet

(2)TreeSet(与HashSet几乎相同,唯一不同是它会对存放的数据进行排序,默认只能存放能排序的数据)

(3)LinkedHashSet 链表 查询速度非常快,但添加和删除慢(不常用)

HashSet:

package com.fyypll.set;

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

public class TestHashSet {

    public static void main(String[] args) {
        
        // 1. 如何实例化(3种)
        // ①
        HashSet hs1 = new HashSet(); // 没有泛型,hs1里面就可以存放任意类型的数据,不推荐这种方法
        hs1.add("abcd");
        hs1.add(123465);
        
        // ②
        HashSet<String> hs2 = new HashSet<>();
        
        // ③
        // HashSet 实现了Set接口,可以向上转型
        Set<String> hs3 = new HashSet<>();
        hs3.add("诸葛亮");
        hs3.add("刘备");
        hs3.add("关羽");
        hs3.add("张飞");
        hs3.add("刘备");
        hs3.add(null); // HashSet中元素可以为null,但也只能有一个空值,重复的会被覆盖
        hs3.add(null);
        
        System.out.println(hs3.size()); // 集合中元素的个数
        // 打印集合中的全部数据,因为HashSet重写了toString方法
        // 所以这里我们可以直接用toString即可打印出HashSet中的元素
        System.out.println(hs3.toString()); 
        
        System.out.println("----------遍历HashSet----------");
        
        // 2.如果要取出hs3中的数据该如何做(2种)
        // ①
        for(int i=0;i<hs3.size();i++) {
            // 这个方法循环遍历是不行的,因为set集合中的数据没有下标,那就没法通过下标取出数据喽
        }
        
        // ② 使用增强for,增强for取数据不需要下标哦
        for(String s : hs3) {
            System.out.println(s);
        }
        
        // ③
        System.out.println("----------Iterator 迭代器---------");
        
        // 调用HashSet类中的iterator方法获取迭代器
        // 迭代器泛型类型跟HashSet(hs3)的泛型类型一致
        Iterator<String> iterator = hs3.iterator();
        
        // 使用迭代器
        while(iterator.hasNext()) { // hasNext判断迭代器中是否还有数据,如果有,返回true
            
            // next方法从迭代器中取出一个数据(取出的是哪一个我们不知道,因为set数据没有顺序)
            // 每取出一个数据,就将该数据从迭代器中删除(所以数据只能拿出来一次,因为一拿出来从迭代器中就删除了)
            // 因为迭代器是String类型,所以这里用String类型的s来接收数据
            String s = iterator.next(); 
            System.out.println(s);
        }
        
        System.out.println("----------删除数据-----------");
        // 删除数据
        // 因为set中的数据没有下标,所以要删除哪个数据就需要传哪个数据
        hs3.remove("刘备");
        System.out.println("删除之后:"+hs3.toString());
        
        System.out.println("----------批量操作-----------");
        // 批量操作(添加、删除)
        // 先创建两个集合,以便后面使用
        Set<String> hs4 = new HashSet<>();
        hs4.add("三国");
        hs4.add("演义");
        
        Set<String> hs5 = new HashSet<>();
        hs5.add("关羽");
        hs5.add("张飞");
        
        // 批量添加:使用addAll方法添加整个集合hs4到hs3中(即合并两个集合)
        hs3.addAll(hs4);
        System.out.println("批量添加之后:"+hs3.toString());
        
        // 批量删除:使用removeAll方法将会删除所有hs3中与hs5中相同的数据
        // 即hs3中的所有数据,只要是和hs5中的数据相同的,都会被删除
        hs3.removeAll(hs5);
        System.out.println("批量删除之后:"+hs3.toString());
        
        // 把hs3集合转换为数组
        String[] a = hs3.toArray(new String[hs3.size()]);
    }

}

HashSet代码运行结果:

5
[关羽, null, 张飞, 刘备, 诸葛亮]
----------遍历HashSet----------
关羽
null
张飞
刘备
诸葛亮
----------Iterator 迭代器---------
关羽
null
张飞
刘备
诸葛亮
----------删除数据-----------
删除之后:[关羽, null, 张飞, 诸葛亮]
----------批量操作-----------
批量添加之后:[关羽, null, 张飞, 诸葛亮, 演义, 三国]
批量删除之后:[null, 诸葛亮, 演义, 三国]

HashSet代码解析:

代码31行运行结果为5set中的数据是不重复的,所以虽然传入的是7个值,但是输出的元素统计个数为5(输入的值中刘备null重复了)。代码32行运行结果为[关羽, null, 张飞, 刘备, 诸葛亮],输出顺序和我们输入的顺序并不一样,可见set中的数据是无序的。

注释中说过因为HashSettoString方法重写了,所以我们能直接使用toString方法将HashSet中的数据直接打印出来。通过查看JDK源代码可以找到重写代码如下:

public String toString() {
    Iterator<E> it = iterator();
    if (! it.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = it.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! it.hasNext())
            return sb.append(']').toString();
        sb.append(',').append(' ');
    }
}

这里可以很清楚的看出来,如果数据集里面没有数据,就会直接输出[],如果有数据那么就会先输出一个[然后后面用append方法将逐个输出的数据拼接起来,直到数据输完然后拼接上]

HashSet总结:

HashSet中:

add 添加元素

remove 删除元素

size() 元素个数

遍历HashSet使用增强for或迭代器iterator

TreeSet:

package com.fyypll.set;

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

public class TestTreeSet {

    public static void main(String[] args) {

        // 实例化方式和HashSet一样,有3种
        // ①
        TreeSet ts1 = new TreeSet();
        // ②
        TreeSet<Integer> ts2 = new TreeSet<>();
        
        // ③ 因为TreeSet实现了Set接口,所以可以向上转型
        Set<Integer> ts3 = new TreeSet<>();
        
        ts3.add(888);
        ts3.add(666);
        ts3.add(777);
        // toString方法是Object类中的方法
        // 因为TreeSet重写了toString方法,所以用toString就能打印出结果
        // Integer类型输出结果是从小到大
        System.out.println(ts3.toString()); // [666, 777, 888]
        
        Set<String> ts4 = new TreeSet<>();
        ts4.add("bbb");
        ts4.add("ab");
        ts4.add("ccc");
        ts4.add("Ddd");
        // String类型中字母是按字母顺序排的,字符串长度不一就按首字母排,首字母一样就按第二个字母排
        // 大写字母优先排
        System.out.println(ts4.toString()); // [Ddd, ab, bbb, ccc]
        
        Set<String> ts5 = new TreeSet<>();
        ts5.add("可"); // \u53ef
        ts5.add("能"); // \u80fd
        ts5.add("是"); // \u662f
        // String类型中汉字是按照 Unicode 编码来排序的,首字母都是u,判断第二位,第二位都是数字,
        // 按小到大排就是 “\u53ef \u662f \u80fd”,即 “可 是 能”,如果第二位有数字和字母那怎么排?
        // 那就按16进制来比大小,即将字母看成数字,然后比大小,即a=10,b=11,c=12,d=13,e=14,f=15
        System.out.println(ts5.toString()); // [可, 是, 能]
        
    }

}

TreeSet代码运行结果:

[666, 777, 888]
[Ddd, ab, bbb, ccc]
[可, 是, 能]

TreeSet总结:

HashSet几乎相同,唯一不同是它会对存放的数据进行排序,默认只能存放能排序的数据。

分类: 后端Other 标签: 编程Java

评论

暂无评论数据

暂无评论数据

目录