JAVA基础|集合框架-Collection,Map

一. Collection和Map的区别

Collection是一个单列集合,Map是一个双列集合。那么什么是单列集合,什么是双列集合呢?

单列集合,就是每个数据只包含一个值,而双列集合就是每个数据包含两个值(键值对)

二. Collection

(一)Collection集合特点:

List系列集合:添加的元素是有序,可重复,有索引。

  • ArrayList,LinkedList: 有序,可重复,有索引

Set系列集合:添加的元素是无序,不重复,无索引。

  • HashSet:无序,不重复,无索引
  • LinkedHashSet:有序,不重复,无索引
  • TreeSet:按照大小默认升序排序,不重复,无索引

(二)Collection的常用方法

1. public boolean add (E e); 添加元素,添加成功返回true
2. public void clear(); 清空集合元素
3. public boolean isEmpty(); 判断集合是否为空,是空返回true
4. public int size(); 获取集合的大小
5. public boolean contains(Object obj); 判断集合中是否包含某个元素
6. public boolean remove(E e); 删除某个元素:如果有多个重复元素默认删除前面的第一个
7. public Object[] toArray(); 把集合转换为数组
import java.util.ArrayList;
import java.util.Collection;

public class CollectionTest2API {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        //1. public boolean add (E e); 添加元素,添加成功返回true
        c.add("A");
        c.add("B");
        c.add("C");
        c.add("D");
        c.add("E");
        System.out.println(c);

        //2. public void clear(); 清空集合元素
        c.clear();
        System.out.println(c);

        //3. public boolean isEmpty(); 判断集合是否为空,是空返回true
        System.out.println(c.isEmpty());

        //4. public int size(); 获取集合的大小
        System.out.println(c.size());

        //5. public boolean contains(Object obj); 判断集合中是否包含某个元素
        System.out.println(c.contains("A"));
        System.out.println(c.contains("G"));

        //6. public boolean remove(E e); 删除某个元素:如果有多个重复元素默认删除前面的第一个
        System.out.println(c.remove("A"));
        System.out.println(c);
        
        //7. public Object[] toArray(); 把集合转换为数组
        Object[] arr = c.toArray();
        
        String[] arr2 = c.toArray(new String[c.size()]);    //将集合强制转换为String类型的数组,而非Object类型的数组
        System.out.println(Arrays.toString(arr2));
    }
}

将一个集合的数据全部倒入到另一个集合中去:

要注意两个集合的数据类型要一致。只是将c2中的数据拷贝并倒入。

Collection<String> c1 = new ArrayList<>();
c1.add("java1");
c1.add("java2");
Collection<String> c2 = new ArrayList<>();
c2.add("java3");
c2.add("java4");
c1.addAll(c2);

(三)Collection的遍历方式

1. 迭代器

迭代器是用来遍历集合的专用方式(数组没有迭代器),在Java中迭代器的代表是Iterator

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

public class CollectionDemo01 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("a");
        c.add("b");
        c.add("c");
        c.add("d");
        System.out.println(c);

        //使用迭代器遍历集合
        //1. 从集合对象中获取迭代器对象
        Iterator<String> it = c.iterator();
        //2. 使用循环结合迭代器遍历集合
        while (it.hasNext()) {
            String ele = it.next();
            System.out.println(ele);
        }
    }
}

注意,迭代器可以遍历集合,但不能遍历数组

2. 增强for循环

格式:

for (元素的数据类型 变量名:数组或者集合) {

}

  • 增强for可以用来遍历集合或者数组
  • 增强for遍历集合,本质就是迭代器遍历集合的简化写法
public class CollectionDemo02 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("a");
        c.add("b");
        c.add("c");
        c.add("d");
        System.out.println(c);

        //使用增强for遍历集合
        for (String ele:c) {
            System.out.println(ele);
        }
    }
}

增强for循环可以用来遍历数组

public class CollectionDemo02 {
    public static void main(String[] args) {
        //使用增强for遍历数组
        String[] names = {"a","b","c","d"};
        for (String ele:names) {
            System.out.println(ele);
        }
    }
}

3. Lambda表达式遍历集合

得益于JDK 8开始的新技术Lambda表达式,提供了一种更简单,更方便的遍历方式。

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;

public class CollectionDemo03 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("a");
        c.add("b");
        c.add("c");
        c.add("d");
        System.out.println(c);

        //default void forEach(Consumer<? super T>action): 结合Lambda表达式遍历集合
        c.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        
        //第一步简化:
        c.forEach((String s) -> System.out.println(s));
        
        //第二步简化:
        c.forEach(s -> System.out.println(s));
        
        //第三步简化:
        c.forEach(System.out::println);
    }
}

4. 案例

需求:展示多部电影信息

分析:

  • 每部电影都是一个对象,多部电影要使用集合装起来。
  • 遍历集合中的3个电影对象,输出每部电影的详情信息。

(四)List集合

List系列集合特点:有序,可重复,有索引。

  • List集合因为支持索引,所以多了很多与索引相关的方法,当然,Collection的功能List也都继承了。

1. 常用方法

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

public class ListTest01 {
    public static void main(String[] args) {
        //1. 创建一个ArrayList集合对象(有序,可重复,有索引)
        List<String> list = new ArrayList<>();  //一行经典代码
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        System.out.println(list);

        //2. public void add(int index, E element): 在某个索引位置插入元素。
        list.add(1,"e");
        System.out.println(list);

        //3. public E remove(int index): 根据索引删除元素,返回被删除元素
        System.out.println(list.remove(2));
        System.out.println(list);

        //4. public E get(int index): 返回集合中指定位置的元素。
        System.out.println(list.get(3));

        //5. public E set(int index, E element): 修改索引位置处的元素,修改成功后,会返回原来的数据
        System.out.println(list.set(2,"g"));
    }
}

 2. 遍历方式

List集合支持的遍历方式:

  1. for循环(因为List集合有索引)
  2. 迭代器
  3. 增强for循环
  4. Lambda表达式
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListTest02 {
    public static void main(String[] args) {
        //1. 创建一个ArrayList集合对象(有序,可重复,有索引)
        List<String> list = new ArrayList<>();  //一行经典代码
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        
        //(1) for循环
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
        
        //(2) 迭代器
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        
        //(3) 增强for循环(forEach遍历)
        for (String  s:list) {
            System.out.println(s);
        }
        
        //(4) JDK1.8开始之后的Lambda表达式
        list.forEach(s->System.out.println(s));
    }
}

3. ArrayList集合的底层原理

ArrayList和LinkedList底层采用的数据结构不同,应用场景不同。数据结构就是指存储,组织数据的方式。

  • 基于数组实现的         数组的特点:查询速度快(是因为根据索引查询,所以速度快):查询数据通过地址值和索引定位,查询任意数据耗时相同。删除效率低:可能需要把后面很多的数据进行前移。添加效率极低:可能需要把后面很多的数据后移,再添加元素;或者也可能需要进行数组的扩容。

ArrayList适合根据索引查询数据(比如根据随机索引取数据)数据量不是很大的时候但他不适合数据量大的同时,又要频繁的进行增删操作

4. LinkedList集合底层原理

基于双链表实现的

链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。

单向链表:

特点1:查询慢,无论查询哪个数据都要从头开始找。

特点2:链表增删相对快

双向链表:

特点:查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的

LinkedList新增了很多首位操作的特有方法

LinkedList的应用场景之一:可以用来设计队列

特点:先进先出,后进后出

import java.util.LinkedList;

public class ListTest03 {
    public static void main(String[] args) {
        //1. 创建一个队列
        LinkedList<String> queue = new LinkedList<>();
        queue.addLast("第一个人");
        queue.addLast("第二个人");
        queue.addLast("第三个人");
        queue.addLast("第四个人");
        System.out.println(queue);

        //出队
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue);
    }
}

LinkedList的应用场景之一:可以用来设计栈

特点:后进先出,先进后出

只是在首部增删元素,用LinkedList集合实现很适合!

数据进入栈模型的过程称为:压/进栈(push)

数据离开栈模型的过程称为:弹/出栈(pop)

import java.util.LinkedList;

public class ListTest03 {
    public static void main(String[] args) {
        //2. 创建一个栈对象
        LinkedList<String> stack = new LinkedList<>();
        //压栈
        stack.addFirst("第一颗子弹");
        stack.addFirst("第二颗子弹");
        stack.addFirst("第三颗子弹");
        stack.addFirst("第四颗子弹");
        //出栈
        System.out.println(stack.removeFirst());
        System.out.println(stack.removeFirst());
        System.out.println(stack);
    }
}

其实我们可以用push和pop来写,更加优雅,实际上调用的还是addFirst,removeFirst

import java.util.LinkedList;

public class ListTest03 {
    public static void main(String[] args) {
        //2. 创建一个栈对象
        LinkedList<String> stack = new LinkedList<>();
        //压栈
        stack.push("第一颗子弹");
        stack.push("第二颗子弹");
        stack.push("第三颗子弹");
        stack.push("第四颗子弹");
        //出栈
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack);
    }
}

(五)Set集合

1. 特点:

无序:添加数据的顺序和获取出的数据顺序不一致;不重复无索引

  • HashSet:无序,不重复,无索引
  • LinkedHashSet:有序,不重复,无索引
  • TreeSet:排序,不重复,无索引

创建:

set<Integer> set = new HashSet<>();    //创建一个HashSet
set<Integer> set = new LinkedHashSet<>();    //创建一个LinkedHashSet
set<Integer> set = new TreeSet<>();    //创建一个TreeSet

2. HashSet集合的底层原理

在了解HashSet之前,我们需要搞清楚一个前置只是:哈希值

哈希值:

  • 就是一个int类型的数值,Java中每个对象都有一个哈希值。
  • Java中的所有对象,都可以调用Object类提供的hashCode方法,返回该对象自己的哈希值
public int hashCode() : 返回对象的哈希码值

对象哈希值的特点:

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 不同的对象,他们的哈希值一般不相同,但也有可能会相同(被称为哈希碰撞)

为什么呢?因为哈希值是一个int类型的数据,范围在(-21亿多~21亿多),当对象大于45亿个对象时,哈希值就有可能相同了 

HashSet集合的底层原理:

  • 基于哈希表实现
  • 哈希表是一种增删改茶数据,性能都较好的数据结构

哈希表:

  • JDK8之前,哈希表=数组+链表
  • JDK8开始,哈希表=数组+链表+红黑树

问:如果数组快占满了,会出现什么问题?该咋办?

答:链表会过长,导致查询性能降低 。扩容。

问:加载因子干啥的?

答:如何判断当前集合是否要扩容了呢?当前长度*加载因子 = 某个值,当这个值填满了就开始扩容。

JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树

了解一下数据结构(树):

度:每一个节点的子节点数量 (二叉树中,任意节点的度<=2)

树高:树的总层数

根节点:最顶层的节点

左子节点

右子节点

左子树 

二叉排序树

规则:小的存左边,大的存右边,一样的不存 

二叉查找树存在的问题:

解决办法:平衡二叉树:

3. LinkedHashSet集合的底层原理

4. TreeSet集合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值