Java集合框架

Java集合的基本使用

Java集合框架
Collection
List
ArrayList
LinkedList
Vector
Set
HashSet
LinkedHashSet
TreeSet
Map
HashMap
HashTable
LinkedHashMap
TreeMap
Properties
Collections

一、Collection接口

Collection接口中常用的关键方法

  • add:添加单个元素
  • remove:删除指定元素
  • contains:查找元素是否存在
  • size:获取元素个数
  • isEmpty:判断是否为空
  • clear:清空
  • addAll:添加多个元素
  • containsAll:查找多个元素是否都存在
  • removeAll:删除多个元素

(1)List接口

List接口中添加了一些根据索引来操作集合元素的方法:

  • void add(int index, Object ele):在index位置插入ele元素
  • Boolean addAll(int index,Collection eles):在index位置将eles中所有元素插入进来
  • Object get(int index):获取index位置的元素
  • int indexOf(Object obj):获取obj在集合中首次出现的位置
  • int lastIndexOf(Object obj):获取obj在集合中末次出现的位置
  • Object remove(int index):删除index位置的元素,并返回此元素
  • Object set(int index, Object ele):将index位置的元素设置为ele,相当于替换
  • List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
1.ArrayList
  • ArrayList可以存放空元素null,且是可以存放多个空值。
  • 底层是数组,效率高,线程不安全,适用于改查多,增删少的情况。
import java.util.*;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> li = new ArrayList<>();
        li.add(1);  // 添加元素
        li.add(100);
        li.remove(0);  // 删除索引为0的元素
        //li.remove(new Integer(100));  // 删除值为100的元素
        Boolean isEmpty = li.isEmpty();  // 判断是否为空
        int size = li.size();
        if (li.contains(100)) {  // 判断是否存在指定元素
            System.out.println("100存在");
        }
        li.clear();  // 清空集合中所有元素
        List<Integer> ll = new ArrayList<>();
        for (int i = 0; i < 5; i++)
            ll.add(i);
        li.addAll(ll);  // 往集合中添加多个元素
        Boolean isContainsAll = li.containsAll(ll);  // 查找多个元素是否都存在
        li.removeAll(ll);  // 删除多个元素
    }
}
2.LinkedList
  • 底层是双向链表,适用于改查少,增删多的情况。
import java.util.*;

public class Main {
    public static void main(String[] args) {
        LinkedList<Integer> li = new LinkedList<>();
        li.add(1);  // 添加元素
        li.add(100);
        li.remove(0);  // 删除索引为0的元素
        //li.remove(new Integer(100));  // 删除值为100的元素
        Boolean isEmpty = li.isEmpty();  // 判断是否为空
        int size = li.size();
        if (li.contains(100)) {  // 判断是否存在指定元素
            System.out.println("100存在");
        }
        li.clear();  // 清空集合中所有元素
        List<Integer> ll = new LinkedList<>();
        for (int i = 0; i < 5; i++)
            ll.add(i);
        li.addAll(ll);  // 往集合中添加多个元素
        Boolean isContainsAll = li.containsAll(ll);  // 查找多个元素是否都存在
        li.removeAll(ll);  // 删除多个元素
    }
}
3.Vector

相比于ArrayList和LinkedList,Vector是线程安全的,适用于在多线程下使用。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Vector<Integer> li = new Vector<>();
        li.add(1);  // 添加元素
        li.add(100);
        li.remove(0);  // 删除索引为0的元素
        //li.remove(new Integer(100));  // 删除值为100的元素
        Boolean isEmpty = li.isEmpty();  // 判断是否为空
        int size = li.size();
        if (li.contains(100)) {  // 判断是否存在指定元素
            System.out.println("100存在");
        }
        li.clear();  // 清空集合中所有元素
        List<Integer> ll = new Vector<>();
        for (int i = 0; i < 5; i++)
            ll.add(i);
        li.addAll(ll);  // 往集合中添加多个元素
        Boolean isContainsAll = li.containsAll(ll);  // 查找多个元素是否都存在
        li.removeAll(ll);  // 删除多个元素
    }
}

(2)Set接口

Set接口和方法:

  • Set接口无序(添加和取出元素的顺序不一样),没有索引,不支持随机访问
  • 和List接口一样,Set接口也是Collection的子接口,因此常用方法和Collection接口一样
  • Set接口的遍历也可以使用迭代器和增强for循环,但是不能用索引获取
  • 不能有重复的元素/对象
1.HashSet

基本说明:

  • HashSet实现了Set接口,底层实际上是HashMap
  • 可以存放null值,但是只能存放一个(Set中的元素不能重复)
  • HashSet不保证元素是有序的,取决于hash后,再确定索引的结果
  • 不能有重复的元素/对象

注意事项:

  • 在存储对象进HashSet时,对象重写equals方法一定要重写hashCode方法,不然就会出现即使两个对象里面的数据一模一样,但是都可以存进HashSet集合中,因为如果没有重写HashCode方法,对象会使用父类Object类的hashCode方法,而Object的HashCode方法是根据地址来计算的,一定不会一样
  • ==使用的比较地址就是用的hashcode()
import java.util.*;

public class Main {
    public static void main(String[] args) {
        HashSet<Stu> hashSet = new HashSet<>();
        hashSet.add(new Stu(1));
        hashSet.add(new Stu(6));
        hashSet.add(new Stu(5));
        hashSet.add(new Stu(4));
        hashSet.add(new Stu(3));
        hashSet.add(new Stu(8));
        hashSet.add(new Stu(7));
        hashSet.add(new Stu(2));
        hashSet.add(new Stu(1));
        hashSet.add(new Stu(2));

        for (Stu s : hashSet) {
            System.out.println(s);
        }
        /*
            打印顺序:跟插入顺序不一致
            id=1
            id=2
            id=3
            id=4
            id=5
            id=6
            id=7
            id=8
        */
    }
}

class Stu {
    public int id;

    public Stu(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "id=" + this.id;
    }

    // 需要重写hashCode()和equals()
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Stu stu = (Stu) o;
        return id == stu.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
2.LinkedHashSet

基本说明:

  1. LinkedHashSet是HashSet的子类
  2. LinkedHashSet底层是一个LinkedHashMap,底层维护了数组+双向链表
  3. LinkedHashSet根据元素的hashCode来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序来保存的
  4. LinkedHashSet不允许添加重复元素
import java.util.*;

public class Main {
    public static void main(String[] args) {
        LinkedHashSet<Stu> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(new Stu(1));
        linkedHashSet.add(new Stu(6));
        linkedHashSet.add(new Stu(5));
        linkedHashSet.add(new Stu(4));
        linkedHashSet.add(new Stu(3));
        linkedHashSet.add(new Stu(8));
        linkedHashSet.add(new Stu(7));
        linkedHashSet.add(new Stu(2));
        linkedHashSet.add(new Stu(1));
        linkedHashSet.add(new Stu(2));

        for (Stu s : linkedHashSet) {
            System.out.println(s);
        }
        /*
            打印顺序:跟插入顺序一致
            id=1
            id=6
            id=5
            id=4
            id=3
            id=8
            id=7
            id=2
        */
    }
}

class Stu {
    public int id;

    public Stu(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "id=" + this.id;
    }

    // 需要重写hashCode()和equals()
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Stu stu = (Stu) o;
        return id == stu.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

二、集合遍历方式

(1)迭代器

  • Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
  • 所有实现了Collection接口的集合类都有一个Iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
  • Iterator仅用于遍历集合,Iterator本身并不存储对象。
  • 迭代器的执行原理:指针不断下移,直到遍历完集合中的元素。
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Collection<Book> col = new ArrayList<>();
        col.add(new Book("西游记"));
        col.add(new Book("三国演义"));
        col.add(new Book("红楼梦"));

        Iterator<Book> it = col.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        
        // 当退出while循环后,这时iterator迭代器,指向最后的元素
        // iterator.next(); --> NoSuchElementException
        // 如果希望再次遍历,需要重置我们的迭代器
        it = col.iterator();
    }
}

class Book {
    private String name;

    public Book(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                '}';
    }
}

(2)增强for循环

增强for的底层仍然是迭代器,在for循环端点debug就可以看到了,会调用Iterator,增强for可以看成简易版的迭代器。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Collection<Book> col = new ArrayList<>();
        col.add(new Book("西游记"));
        col.add(new Book("三国演义"));
        col.add(new Book("红楼梦"));

        for (Book book : col) {
            System.out.println(book);
        }
    }
}

class Book {
    private String name;

    public Book(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                '}';
    }
}

三、Map

Map基本说明:

  1. Map与Collection并列存在,用于保存具有映射关系的数据key-value
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复,原因和HashSet一样
  4. Map中的value可以重复
  5. Map中的key和value均可以为null,但是key为null只能有一个,value为null可以有多个
  6. 常用String类作为Map的key
  7. key和value之间存在单向一对一的关系,即通过指定的key总能找到对应的value

Map接口常用的关键方法:

  1. put:添加
  2. remove:根据键删除映射关系
  3. get:根据键获取值
  4. size:获取元素个数
  5. isEmpty:判断个数是否为0
  6. clear:清除所有元素
  7. containsKey:查看键是否存在

Map的六大遍历方式:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("邓超", "孙俪");
        map.put("王宝强", "马蓉");
        map.put("宋喆", "马蓉");
        map.put("刘令博", null);
        map.put(null, "刘亦菲");
        map.put("鹿晗", "关晓彤");

        //第一组: 先取出 所有的Key , 通过Key 取出对应的Value
        Set keyset = map.keySet();
        //(1) 增强for
        System.out.println("-----第一种方式-------");
        for (Object key : keyset) {
            System.out.println(key + "-" + map.get(key));
        }
        //(2) 迭代器
        System.out.println("----第二种方式--------");
        Iterator iterator = keyset.iterator();
        while (iterator.hasNext()) {
            Object key =  iterator.next();
            System.out.println(key + "-" + map.get(key));
        }

        //第二组: 把所有的values取出
        Collection values = map.values();
        //这里可以使用所有的Collections使用的遍历方法
        //(1) 增强for
        System.out.println("---取出所有的value 增强for----");
        for (Object value : values) {
            System.out.println(value);
        }
        //(2) 迭代器
        System.out.println("---取出所有的value 迭代器----");
        Iterator iterator2 = values.iterator();
        while (iterator2.hasNext()) {
            Object value =  iterator2.next();
            System.out.println(value);
        }

        //第三组: 通过EntrySet 来获取 k-v
        Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
        //(1) 增强for
        System.out.println("----使用EntrySet 的 for增强(第3种)----");
        for (Object entry : entrySet) {
            //将entry 转成 Map.Entry
            Map.Entry m = (Map.Entry) entry;
            System.out.println(m.getKey() + "-" + m.getValue());
        }
        //(2) 迭代器
        System.out.println("----使用EntrySet 的 迭代器(第4种)----");
        Iterator iterator3 = entrySet.iterator();
        while (iterator3.hasNext()) {
            Object entry =  iterator3.next();
            //System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
            //向下转型 Map.Entry
            Map.Entry m = (Map.Entry) entry;
            System.out.println(m.getKey() + "-" + m.getValue());
        }
    }
}

(1)HashMap

HashMap注意事项:

  1. Map接口的常用实现类:HashMap、Hashtable和Properties
  2. HashMap是Map接口使用频率最高的实现类
  3. HashMap是以key-value对的方式存储数据
  4. key不能重复,但是value可以重复,允许使用null键和null值
  5. 如果添加相同的key,则会覆盖原来的key-value,等同于修改(key不会替换,val会替换)
  6. 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的
  7. HashMap没有实现同步,因此线程是不安全的

(2)Hashtable

Hashtable的使用:

  1. 存放的元素是键值对:即K-V
  2. Hashtable的键和值都不能为null,否则会抛出NullPointerException
  3. Hashtable使用方法基本上和HashMap一致
  4. Hashtable是线程安全的(synchronized),HashMap是线程不安全的

(3)Properties

Properties基本使用:

  1. Properties类继承自Hashtable类并且实现了Map接口,也是一种键值对的形式来保存数据
  2. 使用特点和Hashtable类似
  3. Properties还有可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
  4. xxx.properties文件通常作为配置文件,这个知识点配合IO流加以应用

(4)集合选型规则

在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择:

  1. 先判断存储数据的类型:一组对象/一组键值对
  2. 一组对象:Collection接口
    • 允许重复:List接口
      • 增删多:LinkedList【底层维护了双向链表】
      • 改查多:ArrayList【底层维护了Object类型的可变数组】
    • 不允许重复:Set接口
      • 无序:HashSet【底层是HashMap,维护了一个hash表(数组+链表+红黑树)】
      • 排序:TreeSet
      • 插入和取出的顺序一致:LinkedHashSet【底层维护了数组+双向链表】
  3. 一组键值对:Map接口
    • 键无序:HashMap【底层:哈希表 jdk7:数组+链表 jdk8:数组+链表+红黑树】
    • 键排序:TreeMap
    • 键插入和取出的顺序一致:LinkedHashMap
    • 读取文件:Properties

四、Collections工具类

(1)Collection工具类基本介绍:
  1. Collections是一个操作Set、List和Map等集合的工具类
  2. Collections中提供了一系列静态方法对集合元素进行排序、查询和修改等操作
(2)排序操作:(均为static方法)
  1. reverse(List):反转List中元素的顺序
  2. shuffle(List):对List集合元素进行随机排序
  3. sort(List):根据元素的自然顺序对指定List集合元素按升序排序
  4. sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
  5. swap(List, int, int):将指定list中i处元素和j处元素进行交换
(3)查找、替换
  1. Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
  2. Object max(Collection, Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
  3. Object min(Collection):
  4. Object min(Collection, Comparator):
  5. int frequency(Collection, Object):返回指定集合中指定元素的出现次数
  6. void copy(List dest, List src):将src中的内容复制到dest中
  7. Boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换旧值
import java.util.*;

@SuppressWarnings({"all"})
public class Main {
    public static void main(String[] args) {
        //创建ArrayList 集合,用于测试.
        List list = new ArrayList();
        list.add("tom");
        list.add("smith");
        list.add("king");
        list.add("milan");
        list.add("tom");

//        reverse(List):反转 List 中元素的顺序
        Collections.reverse(list);
        System.out.println("list=" + list);
//        shuffle(List):对 List 集合元素进行随机排序
//        for (int i = 0; i < 5; i++) {
//            Collections.shuffle(list);
//            System.out.println("list=" + list);
//        }

//        sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
        Collections.sort(list);
        System.out.println("自然排序后");
        System.out.println("list=" + list);
//        sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
        //我们希望按照 字符串的长度大小排序
        Collections.sort(list, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                //可以加入校验代码.
                return ((String) o2).length() - ((String) o1).length();
            }
        });
        System.out.println("字符串长度大小排序=" + list);
//        swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

        //比如
        Collections.swap(list, 0, 1);
        System.out.println("交换后的情况");
        System.out.println("list=" + list);

        //Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
        System.out.println("自然顺序最大元素=" + Collections.max(list));
        //Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
        //比如,我们要返回长度最大的元素
        Object maxObject = Collections.max(list, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length() - ((String)o2).length();
            }
        });
        System.out.println("长度最大的元素=" + maxObject);


        //Object min(Collection)
        //Object min(Collection,Comparator)
        //上面的两个方法,参考max即可

        //int frequency(Collection,Object):返回指定集合中指定元素的出现次数
        System.out.println("tom出现的次数=" + Collections.frequency(list, "tom"));

        //void copy(List dest,List src):将src中的内容复制到dest中

        ArrayList dest = new ArrayList();
        //为了完成一个完整拷贝,我们需要先给dest 赋值,大小和list.size()一样
        for(int i = 0; i < list.size(); i++) {
            dest.add("");
        }
        //拷贝
        Collections.copy(dest, list);
        System.out.println("dest=" + dest);

        //boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
        //如果list中,有tom 就替换成 汤姆
        Collections.replaceAll(list, "tom", "汤姆");
        System.out.println("list替换后=" + list);
    }
}

五、课后练习

练习一

在这里插入图片描述

package hspCollection.homework;

import java.util.ArrayList;

/**
 * Created by 此生辽阔 on 2021/7/25 21:00
 */
public class homework01 {
    public static void main(String[] args) {
        news news = new news("新冠确诊病例超干方,数百万印度教信徒赴恒河“圣浴”引民众担忧");
        news news2 = new news("男子突然想起2个月前钓的鱼还在网兜里,捞起一看赶紧放生");
        ArrayList arrayList = new ArrayList();
        arrayList.add(news );
        arrayList.add(news2 );
        for(int i=arrayList.size();i>0;i--)
        {
            news obj=(news)arrayList.get(i-1);
            System.out.println(obj.getTitle().substring(0,15)+"...");
        }
    }
}

class news{
    String title;
    String type;

    @Override
    public String toString() {
        return "news{" +
                "title='" + title + '\'' +
                '}';
    }

    public news(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

练习二

在这里插入图片描述

package com.hspedu.homework;

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

/**
 * @author 韩顺平
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class Homework02 {
    public static void main(String[] args) {

        ArrayList arrayList = new ArrayList();
        Car car = new Car("宝马", 400000);
        Car car2 = new Car("宾利",5000000);
        //1.add:添加单个元素
        arrayList.add(car);
        arrayList.add(car2);
        System.out.println(arrayList);
        //* 2.remove:删除指定元素
        arrayList.remove(car);
        System.out.println(arrayList);
        //* 3.contains:查找元素是否存在
        System.out.println(arrayList.contains(car));//F
        //* 4.size:获取元素个数
        System.out.println(arrayList.size());//1
        //* 5.isEmpty:判断是否为空
        System.out.println(arrayList.isEmpty());//F
        //* 6.clear:清空
        //System.out.println(arrayList.clear(););//clear是void无法打印
        //* 7.addAll:添加多个元素
        System.out.println(arrayList);
        arrayList.addAll(arrayList);//2个宾利
        System.out.println(arrayList);
        //* 8.containsAll:查找多个元素是否都存在
        arrayList.containsAll(arrayList);//T
        //* 9.removeAll:删除多个元素
        //arrayList.removeAll(arrayList); //相当于清空
        //* 使用增强for和 迭代器来遍历所有的car , 需要重写 Car 的toString方法

        for (Object o : arrayList) {
            System.out.println(o);//
        }
        System.out.println("===迭代器===");
        Iterator iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            Object next =  iterator.next();
            System.out.println(next);

        }

    }
}
/**
 * 使用ArrayList 完成对 对象 Car {name, price} 的各种操作
 * 1.add:添加单个元素
 * 2.remove:删除指定元素
 * 3.contains:查找元素是否存在
 * 4.size:获取元素个数
 * 5.isEmpty:判断是否为空
 * 6.clear:清空
 * 7.addAll:添加多个元素
 * 8.containsAll:查找多个元素是否都存在
 * 9.removeAll:删除多个元素
 * 使用增强for和 迭代器来遍历所有的car , 需要重写 Car 的toString方法
 */
class Car {
    private String name;
    private double price;

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

练习三

在这里插入图片描述

package hspCollection.homework;
import java.util.*;

/**
 * Created by 此生辽阔 on 2021/7/25 21:18
 */
public class homework03 {
    public static void main(String[] args) {
        //(1)
        Map<String,Integer> m= new HashMap();
        m.put("jack",650);
        m.put("tom",1200);
        m.put("smith",2900);

        //(2)
        m.put("jack",2600);
        //(3)
        Set<String> strings = m.keySet();
        for(String s:strings)
        {
           m.put(s,m.get(s)+100);
        }

        //(4)

        for(String s:strings)
        {
            System.out.println(s);
        }
        //(5)
        Collection<Integer> values = m.values();
        Iterator<Integer> iterator ;
        iterator = values.iterator();
        while (iterator.hasNext()) {
            Integer next =  iterator.next();
            System.out.println(next);
        }
    }
}

练习四

在这里插入图片描述
在这里插入图片描述

练习五

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值