03Java集合

1. 集合体系

在Java集合中,分为两大类集合派系Map集合(双列集合)和Collection集合(单列集合)
在这里插入图片描述

1. 单列集合

Collection接口是所有单列集合的顶层父类,所有的单列集合都直接或间接实现Collection接口,在Collection接口中,定义了一些的抽象方法为所有的单列集合之规范

  • public boolean add(E e): 把给定的对象添加到当前集合中 。`
  • public void clear() :清空集合中所有的元素。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中。

以上这些方法都是所有单列集合所遵循的规则

        / 创建集合对象,使用多态形式
    	Collection<String> coll = new ArrayList<String>();
    	// 使用方法
    	/ 添加功能  boolean  add(String s)
    	coll.add("小李广");
    	coll.add("扫地僧");
    	coll.add("石破天");
    	System.out.println(coll);

    	/ boolean contains(E e) 判断o是否在集合中存在
    	System.out.println("判断  扫地僧 是否在集合中"+coll.contains("扫地僧"));

    	/boolean remove(E e) 删除在集合中的o元素
    	System.out.println("删除石破天:"+coll.remove("石破天"));
    	System.out.println("操作之后集合中元素:"+coll);
    	
    	/ size() 集合中有几个元素
		System.out.println("集合中有"+coll.size()+"个元素");

		/ Object[] toArray()转换成一个Object数组
    	Object[] objects = coll.toArray();
    	/ 遍历数组
    	for (int i = 0; i < objects.length; i++) {
			System.out.println(objects[i]);
		}

		/ void  clear() 清空集合
		coll.clear();
		System.out.println("集合中内容为:"+coll);
		/ boolean  isEmpty()  判断是否为空
		System.out.println(coll.isEmpty());  

2. 双列集合

Map集合是所有双列集合的顶层父类,在Map集合中没一个元素都是一个键值对的形式存储。
什么是键值对?如下图
在这里插入图片描述
身份证号与姓名,函数中的X与Y等,前一个变量不能重复(身份证号,函数中的X),后一个变量可以重复(姓名,Y),类似的这样的形式称为键值对。(K=X,V=Y)

  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。
  • public V remove(Object key): 把指定的键所对应的键值对元素 在Map集合中删除,返回被删除元素的值。
  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
  • boolean containsKey(Object key) 判断集合中是否包含指定的键。
  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。
  • public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。
        /创建 map对象
        HashMap<String, String>  map = new HashMap<String, String>();

        /添加元素到集合
        map.put("黄晓明", "杨颖");
        map.put("文章", "马伊琍");
        map.put("邓超", "孙俪");
        System.out.println(map);

        /String remove(String key)
        System.out.println(map.remove("邓超"));
        System.out.println(map);

        / 想要查看 黄晓明的媳妇是谁
        System.out.println(map.get("黄晓明"));
        System.out.println(map.get("邓超"));    

使用keySet方法变量双列集合

    //创建Map集合对象 
        HashMap<String, String> map = new HashMap<String,String>();
        /添加元素到集合 
        map.put("胡歌", "霍建华");
        map.put("郭德纲", "于谦");
        map.put("薛之谦", "大张伟");

        /获取所有的键  获取键集
        Set<String> keys = map.keySet();
        / 遍历键集 得到 每一个键
        for (String key : keys) {
          	/key  就是键
            /获取对应值
            String value = map.get(key);
            System.out.println(key+"的CP是:"+value);
        }  
Entry键值对对象

在Map体系集合中,其内容是由一对对的键值对构成的,我们将这些键值对,向上抽取出来,找到其共同特点,定义一个对象,称为Entry键值对对象
在这里插入图片描述
具体方法

  • public Set<Map.Entry<K,V>> entrySet(): 得到一个Set集合,该集合是单列集合,存储的是一个个键值对对象。

方法展示

        / 创建Map集合对象
        HashMap<String, String> map = new HashMap<String,String>();
        / 添加元素到集合
        map.put("胡歌", "霍建华");
        map.put("郭德纲", "于谦");
        map.put("薛之谦", "大张伟");

        /获取键值对的Set集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        /使用迭代器获取迭代对象
        Iterator<Map.Entry<String, String>> iterator = entries.iterator();

        /遍历集合
        while (iterator.hasNext()){
            /获取一个一个键值对对象
            Map.Entry<String, String> next = iterator.next();
            System.out.println(next.getKey()+","+next.getValue());
        }

在遍历上面集合中,使用了迭代器对象,其实迭代器就像一个张表,从表头开始。

2. List集合

List 接口继承自Collection接口,是单列集合的一个重要分支

  • 在List集合中允许出现重复的元素
  • List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致

1. 常用方法

  • public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。
  • public E get(int index):返回集合中指定位置的元素。
  • public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。
  • public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回值的更新前的元素。

这些方法和Collection接口一样,只是在其基础功能上实现增强

2. List的子类

ArrayList集合

ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合

在之前文章中的常用类中,也提到该类都使用方法

LinkedList集合

该集合数据存储的结构是链表结构,是一个双向链表。方便元素添加、删除的集合。

常用方法

  • public void addFirst(E e):将指定元素插入此列表的开头。
  • public void addLast(E e):将指定元素添加到此列表的结尾。
  • public E getFirst():返回此列表的第一个元素。
  • public E getLast():返回此列表的最后一个元素。
  • public E removeFirst():移除并返回此列表的第一个元素。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。
  • public void push(E e):将元素推入此列表所表示的堆栈。
  • public boolean isEmpty():如果列表不包含元素,则返回true。
public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> link = new LinkedList<String>();
        /添加元素
        link.addFirst("abc1");
        link.addFirst("abc2");
        link.addFirst("abc3");
        System.out.println(link);
        / 获取元素
        System.out.println(link.getFirst());
        System.out.println(link.getLast());
        / 删除元素
        System.out.println(link.removeFirst());
        System.out.println(link.removeLast());

        while (!link.isEmpty()) { /判断集合是否为空
            System.out.println(link.pop()); /弹出集合中的栈顶元素
        }

        System.out.println(link);
    }
}

3. Set接口

Set接口和List接口一样,同样继承自Collection接口,Set并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了

  • Set接口中元素无序
  • 存入的元素不出现重复

1. HashSet集合

HashSetSet接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。HashSet底层的实现其实是一个HashMap支持。

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

不重复存储原理
  • 在HashSet集合添加元素时,首先调用HashCode方法计算该元素的Hash值(类似于地址值)
  • 在从集合中查找是否有相同的Hash值,若没有,则添加
  • 若有,则调用equals方法,比较内容是否相同(这里要注意,equals方法本身比较的就是Hash值,使用要覆写元素的equals方法),相同不存储,不相同存储

原理图

在这里插入图片描述

  1. 创建被添加的元素Peson类
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //覆写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    //覆写toString方法
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  1. 测试代码
        / 创建集合对象
        HashSet<Person> set = new HashSet<>();

        / 添加三个相同元素
        set.add(new Person("xxx",2));
        set.add(new Person("xxx",2));
        set.add(new Person("xxx",2));

        System.out.println(set); /显示结果只有一个 [Person{name='xxx', age=2}]
LinkedHashSet集合

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?
在HashSet下面有一个子类LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构。可以使元素有顺序的存储

 Set<String> set = new LinkedHashSet<String>();
        //无序排列
        set.add("bbb");
        set.add("aaa");
        set.add("abc");
        set.add("bbc");
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next()); // 有序输出
        }

结果为
在这里插入图片描述

4. Collections集合工具类

1. 常用方法

  • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
  • public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
  • public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
addAll方法与排序
ArrayList<Integer> list = new ArrayList<Integer>();
        /原来写法
        // list.add(12);
        // list.add(14);
        // list.add(15);
        // list.add(1000);
        // 采用工具类往集合中添加元素
        Collections.addAll(list, 5, 222, 1, 2);
        System.out.println(list);   /[5, 222, 1, 2]
        /默认排序方法
        Collections.sort(list);
        System.out.println(list); /[1, 2, 5, 222]

        /打乱排序
        Collections.shuffle(list);
        System.out.println(list); /[1, 5, 2, 222]
sort方法之指定排序

比较器

  • java.lang.Comparable 接口:该接口主要是在定义类是,直接提前确定好排序规则,相对来说比较固定
  • java.util.Comparator 接口: 该接口主要是在创建对象之后来,在具体排序时确定排序规则,相对来说比较灵活

我们都知道,在Java中的String类,是有固定的排序规则的,查看源码发现,String实现了java.lang.Comparable 接口,源码如下,但是我们没有权限改变源码,所以可以采用第二中方式,曲线救国改变排序方式

String部分源码

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {......}

Comparator接口
该接口中有一个比较的方法

  • public int compare(String o1, String o2) :比较其两个参数的顺序。

两个对象比较的结果有三种:大于,等于,小于。

如果要按照升序排序,由小到大
则o1 小于o2,返回(负数),相等返回0,01大于02返回(正数)
如果要按照降序排序,由大到小
则o1 小于o2,返回(正数),相等返回0,01大于02返回(负数)

        ArrayList<String> list = new ArrayList<String>();
        list.add("cba");
        list.add("aba");
        list.add("sba");
        list.add("nba");
        /排序方法  按照第一个单词的降序,
        /注意这里使用了匿名内部类的方式
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.charAt(0) - o1.charAt(0);
            }
        });
        System.out.println(list);

在这里插入图片描述
如上图所示,从new开始,一直到},将其看成是一个实现Comparator的一个没有名字的类

不使用匿名内部类的方式

  1. 首先定义一个类去实现Comparator接口,如下
class xx implements Comparator<String>{

    @Override
    public int compare(String o1, String o2) {
        return o2.charAt(0) - o1.charAt(0);
    }
}
  1. 然后使用该类
 ArrayList<String> list = new ArrayList<String>();
        list.add("cba");
        list.add("aba");
        list.add("sba");
        list.add("nba");
        /匿名对象的方式,使用XX类排序模式
        Collections.sort(list,new xx());
        System.out.println(list);

5. Java中数据结构

1.栈

  • stack,又称堆栈,它是运算受限的线性表,其限制是仅允许在标的一端进行插入和删除操作,不允许在其他任何位置进行添加、查找、删除等操作。

简单的说:采用该结构的集合,对元素的存取有如下的特点

  • 先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。

  • 栈的入口、出口的都是栈的顶端位置。
    在这里插入图片描述
    这里两个名词需要注意:

  • 压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。

  • 弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。

2.队列

  • 队列queue,简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。

简单的说,采用该结构的集合,对元素的存取有如下的特点:

  • 先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,小火车过山洞,车头先进去,车尾后进去;车头先出来,车尾后出来。
  • 队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口。

在这里插入图片描述

3.数组

  • 数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。

简单的说,采用该结构的集合,对元素的存取有如下的特点:

  • 查找元素快:通过索引,可以快速访问指定位置的元素

  • 增删元素慢

4.链表

  • 链表:linked list,由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时i动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。我们常说的链表结构有单向链表与双向链表,那么这里给大家介绍的是单向链表

在这里插入图片描述

简单的说,采用该结构的集合,对元素的存取有如下的特点:

  • 多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
    在这里插入图片描述

  • 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素

  • 增删元素快:

    • 增加元素:只需要修改连接下个元素的地址即可。

    • 删除元素:只需要修改连接下个元素的地址即可。

5.红黑树

  • 二叉树binary tree ,是每个结点不超过2的有序树(tree)

简单的理解,就是一种类似于我们生活中树的结构,只不过每个结点上都最多只能有两个子结点。

二叉树是每个节点最多有两个子树的树结构。顶上的叫根结点,两边被称作“左子树”和“右子树”。

如图:

在这里插入图片描述

我们要说的是二叉树的一种比较有意思的叫做红黑树,红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。也就意味着,树的键值仍然是有序的。

红黑树的约束:

  1. 节点可以是红色的或者黑色的
  2. 根节点是黑色的
  3. 叶子节点(特指空节点)是黑色的
  4. 每个红色节点的子节点都是黑色的
  5. 任何一个节点到其每一个叶子节点的所有路径上黑色节点数相同

红黑树的特点:

​ 速度特别快,趋近平衡树,查找叶子元素最少和最多次数不多于二倍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值