【集合】单列集合Collection和双列集合Map简单介绍

集合

集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组的不同之处:

  1. 数组的长度是固定的,集合的长度是可变的。
  2. 数组中存储的是同一类型的元素,一般存储基本数据类型值。集合存储的都是对象,而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。

集合按照其存储结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map。请添加图片描述

Collection接口介绍

单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。其中,

List的特点是元素有序、元素可重复

Set的特点是元素无序,而且不可重复。

List接口的主要实现类有java.util.ArrayList、java.util.LinkedList和java.util.Vector

Set接口的主要实现类有java.util.HashSet和java.util.TreeSet

List接口介绍

List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。

List接口特点:

1.是一个元素存取有序的集合。

2.是一个带有索引的集合,通过索引就可以精确的操作集合中的元素。

3.集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。List接口中常用方法:List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法:

public void add(int index,E element):将指定的元素,添加到该集合中的指定位置上。

public E get(int index):返回集合中指定位置的元素。

public E remove(int index):移除列表中指定位置的元素,返回的是被移除的元素。

public E set(int index,E element):用指定元素替换集合中指定位置的元素,返回值为更新前的元素。

ArrayList集合

默认初始容量为10,如果超过10,那么它会自动扩容:当前容量*1.5

适合随机查找和遍历,不适合插入和删除。

常用方法:

add(E e) 将指定的元素追加到此列表的末尾。

add(int index,E element)在此列表中的指定位置插入指定的元素。

contains(Object o)如果此列表包含指定的元素,则返回true。

get(int index)返回此列表中指定位置的元素。

isEmpty()如果此列表不包含元素,则返回true。

remove(int index)删除该列表中指定位置的元素。

set(int index,E element)用指定的元素替换此列表中指定位置的元素。

size()返回此列表中的元素数

特点:
  1. 排列有序,可重复
  2. 底层使用数组
  3. 查询速度快,增删速度慢
  4. 线程不安全
  5. 初始容量10,当容量不够时,ArrayList是当前容量*1.5

ArrayList遍历方法代码:

package com.yyh.collection.list;

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

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/16 10:31
 * Description:
 * Version: V1.0
 */
public class ForArrayListLinkedList {
    
    
    public static void main(String[] args) {
    
    
        //多态定义方式
        List arrayList = new ArrayList();
        arrayList.add(3);
        arrayList.add(27);
        arrayList.add(34);
        arrayList.add(7);
        arrayList.add(7);
        arrayList.add(12);
//        for (int i = 0; i < arrayList.size() ; i++) {
    
    
//            System.out.println(arrayList.get(i));
//            if (Integer.parseInt(arrayList.get(i).toString()) == 7){
    
    
//                break;
//            }
//        }
        System.out.println(arrayList);
        System.out.println("——————————————————————————————");
        //需求:循环遍历,找元素是7,找到就将其移除。
        //两种解决方法:第一种:for循环中增量直接递减一次。第二种:采用迭代器——推荐使用
        //第一种方法:采用for循环
//        for (int i = 0; i < arrayList.size() ; i++) {
    
    
//            if (Integer.parseInt(arrayList.get(i).toString()) == 7){
    
    
//                arrayList.remove(i);
                i--;  //解决方法一
//            }
//        }
//        System.out.println(arrayList);


        //第二种方法:采用迭代器方式遍历集合
        Iterator it = arrayList.iterator();//以正确的顺序返回该列表中的元素的迭代器
        while(it.hasNext()){
    
        //如果迭代器中还有更多的元素,则返回true
            //返回迭代中的下一个元素
            if (Integer.parseInt(it.next().toString()) == 7){
    
    
                //移除元素
                it.remove();
            }
        }
        System.out.println(arrayList);
    }
}

LinkedList集合

LinkedList是一个双向链表

实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。

public void addFirst(E e):将指定元素插入此列表的开头

public void addLast(E e):将指定元素添加到此列表的结尾

public E getFirst():返回此列表的第一个元素

public E getLast():返回此列表的最后一个元素

public E removeFirst/Last():移除并返回此列表的第一个或者最后一个元素

public E pop():从此列表所表示的堆栈处弹出一个元素

public void push(E e):将元素推入此列表所表示的堆栈

public boolean isEmpty(): 如果列表 不包含元素,则返回true

特点:
  1. 排列有序,可重复
  2. 底层使用双向循环链表数据结构
  3. 查询速度慢,增删快
  4. 线程不安全
Vector集合

Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问Arraylist慢。

特点:
  1. 排列有序,可重复
  2. 底层使用数组
  3. 查询速度快,增删慢
  4. 线程安全,效率低
  5. 初始容量10,当容量不够时,默认扩展一倍容量
Iterator迭代器接口介绍

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator。Iterator接口也是java集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

Iterator接口的常用方法如下:

​ public E next():返回迭代的下一个元素

​ public boolean hasNext():如果仍有元素可以迭代,则返回true。

代码演示:

List arrayList = new ArrayList();
        arrayList.add(3);
        arrayList.add(27);
        arrayList.add(34);
        arrayList.add(7);
        arrayList.add(7);
        arrayList.add(12);

Iterator it = arrayList.iterator();//以正确的顺序返回该列表中的元素的迭代器
        while(it.hasNext()){
    
        //如果迭代器中还有更多的元素,则返回true
            //返回迭代中的下一个元素
            if (Integer.parseInt(it.next().toString()) == 7){
    
    
                //移除元素
                it.remove();
            }
        }
        System.out.println(arrayList);

Set接口介绍

java.util.Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了。与List接口不同的是,Set接口中元素无序没有索引的方法,也不支持普通的for循环遍历,并且都会以某种规则保证存入的元素不出现重复

特点:

  1. 存储元素无序(存储进入的顺序)、且不重复
  2. Set集合没有索引,没有索引的方法,也不支持普通的for循环遍历

Set接口重要的子类:java.util.HashSet、java.util.TreeSet

掌握重要方法,原理:hashCode、equals

HashSet集合
特点:
  1. 存储元素无序(存储进入的顺序)、且不重复
  2. Set集合没有索引,没有索引的方法,也不支持普通的for循环遍历,支持forEach循环遍历(要求:需要指定存放的类型),当然也支持迭代器方式
  3. 底层采用哈希表(数组+链表/红黑树)结构存储,所以效率非常高,存取速度快。
  4. 可以添加一个null值
Hash值

哈希值:哈希值就是一个十进制的整数,就是操作系统随机分配值(也可以理解成对象的地址值,逻辑上的地址值,并不是真正的物理地址。注意:哈希值是模拟的)

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

在jdk1.8之前:HashSet底层机构采用的是哈希表中(数组+链表)

在jdk1.8之后,采用(数组+链表+红黑树)的结构

HashSet通过hashCode值来确定元素在内存中的位置,一个hashCode位置上可以存放多个元素。

根据hash值和equals两个条件判断是否是同一个元素,不是则添加入hashSet中。

HashSet存储自定义类型元素:

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一

定义User类,重写hashCode和equals方法,存入HashSet中:

package com.yyh.collection.set;

import java.util.Objects;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/16 20:49
 * Description:
 * Version: V1.0
 */
public class User extends Object implements Comparable{
    
    
    private String username;
    private String password;
    private double money;

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(username, user.username) &&
                Objects.equals(password, user.password);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(username, password);
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getPassword() {
    
    
        return password;
    }

    public void setPassword(String password) {
    
    
        this.password = password;
    }

    public User() {
    
    
    }

    public User(String username, String password) {
    
    
        this.username = username;
        this.password = password;
    }

    public double getMoney() {
    
    
        return money;
    }

    public void setMoney(double money) {
    
    
        this.money = money;
    }

    public User(String username, String password, double money) {
    
    
        this.username = username;
        this.password = password;
        this.money = money;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", money=" + money +
                '}';
    }

//	对TreeSet对象排列,重写compareTo()
    @Override
    public int compareTo(Object o) {
    
    
        User o2 = (User)o;
        if(this.getMoney() > o2.getMoney()){
    
    
            return 1;
        }
        if(this.getMoney() < o2.getMoney()){
    
    
            return -1;
        }
        return 0;
    }
}

存入HashSet中:

package com.yyh.collection.set;

import java.util.HashSet;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/17 16:59
 * Description:
 * Version: V1.0
 */
public class MyHashSetExample01 {
    
    
    public static void main(String[] args) {
    
    
        User user1 =new User("zhangsan","123");
        User user2 =new User("zhangsan","123");
        System.out.println(user1.hashCode());
        System.out.println(user2.hashCode());
        System.out.println(user1.equals(user2 ));
        HashSet<User> hashSet = new HashSet<User>();
        hashSet.add(user1);
        hashSet.add(user2);
        System.out.println(hashSet);
    }
}

TreeSet集合
  1. TreeSet()是使用二叉树的原理对新add()的对象按照指定的顺序排序(升序、降序),每增加一个对象都会进行排序,将对象插入二叉树指定的位置。
  2. Integer和String对象都可以进行默认的TreeSet排序,而自定义类的对象是不可以的,自己定义的类必须实现Comparable接口,并且覆写相应的compareTo()函数,才可以正常使用。
  3. 在覆写compare()函数时,要返回相应的值才能使TreeSet按照一定的规则来排序。
  4. 比较此对象与指定对象的排序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
特点:
  1. 无序且不重复(默认内部有自然排序机制)
  2. 底层采用TreeMap,二叉树实现,内部是TreeMap的SortedSet
  3. 插入相同元素不是覆盖,而是直接不添加
  4. TreeSet中不能添加null
  5. 没有get()这个方法,因为是无序的
  6. TreeSet不能直接添加对象,因为他无法进行自然排序。
  7. TreeSet如果要进行对象排序,有两种方式可实现:1.内部类方式实现Comparator,2.实现接口Comparable
    TreeSet存入对象:
package com.yyh.collection.set;

import java.util.Comparator;
import java.util.HashSet;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/17 17:12
 * Description:
 * Version: V1.0
 */
public class TreeSetExample01 {
    
    
    public static void main(String[] args) {
    
    
        TreeSet<Integer> treeSet = new TreeSet();
        //默认自然排序机制,与HashSet不同
        treeSet.add(1);
        treeSet.add(7);
        treeSet.add(4);
        treeSet.add(3);
        treeSet.add(9);
        treeSet.add(2);
        System.out.println(treeSet);
        //默认情况,TreeSet中不能直接存放对象,要想存放对象需要进行对象排序规则编写。
        //1.内部类方式实现Comparator,2.实现接口Comparable
        //方法一:内部类方法
//        User user1 =new User("zhangsan","123",1000);
//        User user2 =new User("zhangsan","123",2000);
//        TreeSet<User> treeSet2 = new TreeSet<User>(new Comparator<User>() {
    
    
//            @Override
//            public int compare(User o1, User o2) {//自己制定排序的规则,返回值需要参考API
//                if(o1.getMoney() > o2.getMoney()){
    
    
//                    return 1;
//                }
//                if(o1.getMoney() < o2.getMoney()){
    
    
//                    return -1;
//                }
//                return 0;
//            }
//        });
//        treeSet2.add(user1);
//        treeSet2.add(user2);
//        System.out.println(treeSet2);

//		方法二:修改User中的compareTo方法:(User代码在上面)
        User user1 =new User("zhangsan","123",1000);
        User user2 =new User("zhangsan","123",2000);
        TreeSet<User> treeSet2 = new TreeSet<User>();
        treeSet2.add(user1);
        treeSet2.add(user2);
        System.out.println(treeSet2);
    }
}

Map接口介绍

java提供了专门的集合类用来存放映射关系的对象,即java.util.Map接口。

Collection中的集合,元素是孤立存在的,向集合中存储元素采用一个个元素的方式存储。Map中的集合,元素是成对存在的,每个元素由键与值两部分组成,通过键可以找到所对应的值。Collection中的集合称为单列集合,Map中的集合称为双列集合。需要注意的是Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

通过查看Map接口描述,可以看到Map有多个子类,例:HashMap集合、TreeMap集合、Hashtable集合、LinkedHashMap集合。

HashMap集合

HashMap存储自定义类型键值,键值对方式:即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。

在HashMap中存放元素key原理和HashSet一致,如果key重复,value值覆盖重复元素。

put(K key, V value) 添加元素

get(Object key) 获取key对应的value值

keySet() 返回此地map中包含的键的Set视图

特点:

  1. 键不可重复,值可重复
  2. 底层哈希表
  3. 线程不安全
  4. 允许key值为null,value也可以为null

HashMap的几种遍历方式:

package com.yyh.map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: Santo
 * Date: 2022/03/18 15:22
 * Description:
 * Version: V1.0
 */
public class HashMapExample01 {
    
    
    public static void main(String[] args) {
    
    
        HashMap<String,Object> hashMap = new HashMap<String,Object>();
        //添加元素
        hashMap.put("key01","张三");
        hashMap.put("key02","李四");
        hashMap.put("key03","王五");
        hashMap.put("key04","王五");
        hashMap.put("key05","王五");
        System.out.println(hashMap);
        System.out.println(hashMap.get("key03"));
        //HashMap几种遍历方法:
//      1.迭代器得到String,keySet方法返回此地图中包含的Set视图
//        Set set = hashMap.keySet();
//        Iterator it = set.iterator();
//        while(it.hasNext()){
    
    
//            System.out.println(it.next());
//        }

//        2.通过foreach方式得到两个值
//        Set<String> sets = hashMap.keySet();
//        for (String key:sets
//             ) {
    
    
//            System.out.println(key+"="+hashMap.get(key));
//        }

        //3.遍历Set<Map.Entry<K,V>>,entrySet返回此地图中包含的映射的Set视图
        Set<Map.Entry<String, Object>> entrySet = hashMap.entrySet();
        for (Map.Entry<String,Object> map:entrySet
             ) {
    
    
            String key = map.getKey();
            Object value = map.getValue();
            System.out.println(key+"="+value);
        }

    }
}

TreeMap集合

TreeMap中key存储原理和TreeSet是一样的

TreeMap中键不允许为null,值可以为null

特点:

  1. 键不可重复,值可以重复
  2. 底层二叉树
  3. 不允许key为null,值可以为null

Hashtable集合

Hashtable底层机构,原理,方法和HashMap大致相同

和HashMap不同点:1.Hashtable是线程安全的,HashMap是非线程安全。2.Hashtable效率低,HashMap效率高,常规开发中基本使用HashMap。3.键值都不允许为null。

LinkedHashMap集合

HashMap下的子类,是链表和哈希表组合的一个数据存储结构,有序并且速度快。

特点:

  1. 采用hash表存储,并用双向链表记录插入顺序
  2. 内部是LinkedHashMap

泛型概述

Collection虽然可以存储各种对象,但实际上通常Collection只存储同一类型对象。

泛型:可以在类或方法中预支地使用未知的类型。一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

使用泛型的好处:将运行十七的ClassCastException,转移到了编译时期变成了编译失败。避免了类型强转的麻烦。

泛型的定义与使用:泛型用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。

定义格式:

修饰符 class 类名<代表泛型的变量>{ }

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }

interface 接口名<代表泛型的变量>{ }

Collections工具类

此类仅有静态方法组合或返回集合。包含对集合进行操作的多态算法,“包装器”,返回由指定集合支持的新集合,以及其他一些可能的和最终的。

猜你喜欢

转载自blog.csdn.net/shadowburn1ng/article/details/123589524