集合Collection,Map


一、集合

集合分为两类:一类是单列集合元素是一个一个的,另一类是双列集合元素是一对一对的。

  • Collection代表单列集合,每个元素(数据)只包含一个值。
  • Map代表双列集合,每个元素包含两个值(键值对)。

二、Collection单列集合

在这里插入图片描述

Collection集合特点

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

  • ArrayList、LinekdList :有序、可重复、有索引。

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

  • HashSet: 无序、不重复、无索引;

  • LinkedHashSet: 有序、不重复、无索引。

  • TreeSet:按照大小默认升序排序、不重复、无索引。


  • Collection规定的方法(功能)是全部单列集合都会继承的。

Collection的常见方法:

方法名说明
public boolean add(E e)把给定的对象添加到当前集合中
public void clear()清空集合中所有的元素
public boolean remove(E e)把给定的对象在当前集合中删除
public boolean contains(Object obj)判断当前集合中是否包含给定的对象
public boolean isEmpty()判断当前集合是否为空
public int size()返回集合中元素的个数。
public Object[] toArray()把集合中的元素,存储到数组中
//8.把集合转换为指定类型的数组,可以使用下面的代码
String[] array1 = c.toArray(new String[c.size()]);
System.out.println(Arrays.toString(array1)); //[java1,java2, java2, java3]

三、集合的遍历方式

1.迭代器

概述

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

Collection集合获取迭代器的方法

方法名称说明
Iterator iterator()返回集合中的迭代器对象,该迭代器对象默认指向当前集合的第一个元素

Iterator迭代器中的常用方法

方法名称说明
boolean hasNext()询问当前位置是否有元素存在,存在返回true ,不存在返回false
E next()获取当前位置的元素,并同时将迭代器对象指向下一个元素处。
Collection<String> c = new ArrayList<>();
Iterator<String> it = c.iterator();
while(it.hasNext()){
    String e = it.next();
    System.out.println(s);
}

1.当调用iterator()方法获取迭代器时,当前指向第一个元素
2.hasNext()方法则判断这个位置是否有元素,如果有则返回true,进入循环
3.调用next()方法获取元素,并将当月元素指向下一个位置,
4.等下次循环时,则获取下一个元素,依此内推

2.增强for循环

  • 增强for可以用来遍历集合或者数组。
  • 增强for遍历集合,本质就是迭代器遍历集合的简化写法。
//格式
for(元素的数据类型 变量名 : 数组或者集合) {//在此处使用变量即可,该变量就是元素
}
//
Collection<String> c = new ArrayList<>();
for(String s: c){
    System.out.println(s); 
}

3.forEach遍历集合
常用方法

方法名称说明
default void forEach(Consumer<? super T> action)结合lambda遍历集合
Collection<String> lists = new ArrayList<>();
 lists.forEach(new Consumer<String>() {
   @Override
   public void accept(String s) {
     System.*out*.println(s);
   }
 });
 // 简化
lists.forEach(s -> {
       System.*out*.println(s);
   });
// 继续简化
lists.forEach(s -> System.out.println(s));*

四、List集合

1.List的方法

  • List集合支持索引,Collection的功能List也都继承了。
方法名称说明
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素

List遍历

  • 普通for循环(List有索引)
  • 迭代器
  • 增强for
  • Lambda表达式

2.ArrayList
ArrayList底层的原理
ArrayList集合底层是基于数组结构实现的,也就是说当你往集合容器中存储元素时,底层本质上是往数组中存储元素。

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

原理
①利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
②添加第一个元素时,底层会创建一个新的长度为10的数组
③存满时,会扩容1.5倍
④如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准

ArrayList集合适合的应用场景
ArrayList适合:根据索引查询数据比如根据随机索引取数据(高效)!或者数据量不是很大时!
ArrayList不适合:数据量大的同时又要频繁的进行增删操作!

3. LinkedList
LinkedList底层原理
基于双链表实现的。
特点:查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的。
链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。

方法名称说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素

LinkedList的应用场景:可设计队列
队列的特点:先进先出,后进后出

五、Set集合

1.Set集合
Set要用到的常用方法,基本上就是Collection提供的
Set系列集合特点:无序:添加数据的顺序和获取出的数据顺序不一致; 不重复; 无索引
HashSet : 无序、不重复、无索引。
LinkedHashSet:有序、不重复、无索引。
TreeSet:排序、不重复、无索引。

2.哈希值
就是一个int类型的数值,ava中每个对象都有一个哈希值。
Java中的所有对象,都可以调用Obejct类提供的hashCode方法,返回该对象自己的哈希值。

public int hashCode():返回对象的哈希码值。

对象哈希值的特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的。
不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞)。

哈希表是一种增删改查数据性能都较好的结构

3.HashSet集合
HashSet集合底层原理
HashSet集合底层是基于哈希表实现的,哈希表根据JDK版本的不同,也是有点区别的

  • JDK8以前:哈希表 = 数组+链表

创建一个默认长度16,默认加载因为0.75的数组,数组名table
② 根据元素的哈希值跟数组的长度计算出应存入的位置
判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组。
当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍
JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面
JDK 8开始之后,新元素直接挂在老元素下面

HashSet集合中存储元素时,底层调用了元素的两个方法:一个是hashCode方法获取元素hashCode值(哈希值);另一个是调用了元素的equals方法,用来比较新添加的元素和集合中已有的元素是否相同。

  • 只有新添加元素的hashCode值和集合中以后元素的hashCode值相同、新添加的元素调用equals方法和集合中已有元素比较结果为true, 才认为元素重复。
  • 如果hashCode值相同,equals比较不同,则以链表的形式连接在数组的同一个索引为位置

  • JDK8以后:哈希表 = 数组+链表+红黑树
    JDK8开始后,为了提高性能,当链表的长度超过8时,就会把链表转换为红黑树
    在这里插入图片描述
    在这里插入图片描述

HashSet去重原理
HashSet集合默认不能对内容一样的两个不同对象去重复!
比如内容一样的两个学生对象存入到HashSet集合中去, HashSet集合是不能去重复的!
要想保证在HashSet集合中没有重复元素,需要重写元素类的hashCode和equals方法。

4.LinkedHashSet底层原理

  • LinkedHashSet类是HashSet的子类

底层原理
LinkedHashSet底层采用的是也是哈希表(数组,链表,红黑树)结构,只不过额外新增了一个双向链表来维护元素的存取顺序。

特点
有序、不重复、无索引

5.TreeSet集合
特点:不重复、无索引、可排序(默认升序排序 ,按照元素的大小,由小到大排序)
底层是基于红黑树实现的排序。

注意
对于数值类型:Integer , Double,默认按照数值本身的大小进行升序排序。
对于字符串类型:默认按照首字符的编号升序排序。
对于自定义类型如Student对象,TreeSet默认是无法直接排序的。

自定义排序规则
TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则。
方式一
让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。


public class Student implements Comparable<Student>{
    private String name;
    private int age;
    private double height;
	//无参数构造方法
    public Student(){}
    //全参数构造方法
    public Student(String name, int age, double height){
        this.name=name;
        this.age=age;
        this.height=height;
    }
    //...get、set、toString()方法自己补上..
    
    //按照年龄进行比较,只需要在方法中让this.age和o.age相减就可以。
    /*
    原理:
    在往TreeSet集合中添加元素时,add方法底层会调用compareTo方法,根据该方法的
    结果是正数、负数、还是零,决定元素放在后面、前面还是不存。
    */
    @Override
    public int compareTo(Student o) {
        //this:表示将要添加进去的Student对象
        //o: 表示集合中已有的Student对象
        return this.age-o.age;
    }
}

方式二
通过调用TreeSet集合有参数构造器,可以设置Comparator对象(比较器对象,用于指定比较规则。)

public TreeSet(Comparator<? super E> comparator)
Set<Student> students = new TreeSet<>(new Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2){
        //需求:按照学生的身高排序
        return Double.compare(o1,o2); 
    }
});

两种方式中,关于返回值的规则:

  • 如果认为第一个元素 > 第二个元素 返回正整数即可。
  • 如果认为第一个元素 < 第二个元素返回负整数即可。
  • 如果认为第一个元素 = 第二个元素返回0即可,此时Treeset集合只会保留一个元素,认为两者重复。

注意:如果类本身有实现Comparable接口,TreeSet集合同时也自带比较器,默认使用集合自带的比较器排序。

6.总结

1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)
2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?
用LinkedList集合(有序、可重复、有索引),底层基于双链表实现的。
3.、如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。 (常用)
4、如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
用LinkedHashSet集合(有序,不重复,无索引), 底层基于哈希表和双链表。
5、如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
用TreeSet集合,基于红黑树实现。

6.Collection的其他操作

可变参数

  • 可变参数是一种特殊的形式参数,定义在方法、构造器的形参列表处,它可以让方法接收多个同类型的实际参数。
  • 可变参数在方法内部,本质上是一个数组
public class ParamTest{
    public static void main(String[] args){
        //不传递参数,下面的nums长度则为0, 打印元素是[]
        test();	
        
        //传递3个参数,下面的nums长度为3,打印元素是[10, 20, 30]
        test(10,20,30); 
        
        //传递一个数组,下面数组长度为4,打印元素是[10,20,30,40] 
        int[] arr = new int[]{10,20,30,40}
        test(arr); 
    }
    
    public static void test(int...nums){
        //可变参数在方法内部,本质上是一个数组
        System.out.println(nums.length);
        System.out.println(Arrays.toString(nums));
        System.out.println("----------------");
    }
}
  • 一个形参列表中,只能有一个可变参数;否则会报错
  • 一个形参列表中如果多个参数,可变参数需要写在最后;否则会报错

Collections工具类
Collections并不是集合,它比Collection多了一个s,一般后缀为s的类很多都是工具类。这里的Collections是用来操作Collection的工具类。


待续未完

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值