Java基础学习笔记:第八章 Java集合

Java 集合概述

Java 集合可分为 Collection 和 Map 两种体系
Collection接口:表示不按添加顺序存放对象的集合,集合内元素可以重复,即“无序可重复”集合

Set:元素无序、不可重复的集合 ---类似高中的“集合”
List:元素有序,可重复的集合  ---”动态”数组

Map接口:具有映射关系“key-value对”的集合

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

Collection 接口

Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。

JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。

在 Java5 之前,Java 集合会丢失容器中所有对象的数据类型,把所有对象都当成 Object 类型处理;从 Java5 增加了泛型以后,Java 集合可以记住容器中对象的数据类型
在这里插入图片描述
在这里插入图片描述

练习:
public class TestFor {
      public static void main(String[] args){
             String[] str = new String[5];
             for(String myStr : str){
                    myStr = "atguigu";
                    System.out.println(myStr);
              }
             for(int i = 0;i < str.length;i++){
                    System.out.println(str[i]);
             }
       }
}

Set 接口

Set接口是Collection的子接口,set接口没有提供额外的方法
Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法

HashSet

HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。
HashSet 具有以下特点:

不能保证元素的排列顺序
HashSet 不是线程安全的
集合元素可以是 null

当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等

LinkedHashSet

LinkedHashSet 是 HashSet 的子类
LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
LinkedHashSet 不允许集合元素重复。

TreeSet

TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。

Comparator comparator()
Object first()
Object last()
Object lower(Object e)
Object higher(Object e)
SortedSet subSet(fromElement, toElement)
SortedSet headSet(toElement)
SortedSet tailSet(fromElement)

TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。

List接口

Java中数组用来存储数据的局限性
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。

ArrayList

ArrayList 是 List 接口的典型实现类
本质上,ArrayList是对象引用的一个变长数组
ArrayList 是线程不安全的,而 Vector 是线程安全的,即使为保证 List 集合线程安全,也不推荐使用Vector
Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合

LinkedList

对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
新增方法:

void addFirst(Object obj)
void addLast(Object obj)	
Object getFirst()
Object getLast()
Object removeFirst()
Object removeLast()
Vector

Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。
在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。
新增方法: (这些方法是冗余的,有替代方法,了解即可 )

void addElement(Object obj)
void insertElementAt(Object obj,int index)
void setElementAt(Object obj,int index)
void removeElement(Object obj)
void removeAllElements()

使用 Iterator 接口遍历集合元素

Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。

所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。

Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建 Iterator 对象,则必须有一个被迭代的集合。

在这里插入图片描述

Map接口

Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
Map 中的 key 和 value 都可以是任何引用类型的数据
Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value。

在这里插入图片描述

HashMap

Map接口的常用实现类:HashMap、TreeMap和Properties。
HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

LinkedHashMap

LinkedHashMap 是 HashMap 的子类
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

TreeMap

TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
TreeMap 的 Key 的排序:

自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口

TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
若使用自定义类作为TreeMap的key,所属类需要重写equals()和hashCode()方法,且equals()方法返回true时,compareTo()方法应返回0。

操作集合的工具类:Collections

Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
排序操作:(均为static方法)

reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换

Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
经典面试题
HashSet set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");

set.add(p1);
set.add(p2);
p1.name = "CC";
set.remove(p1);
System.out.println(set);
set.add(new Person(1001,"CC"));
System.out.println(set);
set.add(new Person(1001,"AA"));
System.out.println(set);

        public static void main(String[] args) {
		Integer[] datas = {1,2,3,4,5};
		List<Integer> list = Arrays.asList(datas);
		list.add(5);
		System.out.println(list.size());
	}

总结代码

package com.atguigu.javase.collection;

import org.junit.Test;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import java.util.*;

/**
 * 集合 : 解决批量对象的存储问题.
 * 简单地看作是一个可变长度的Object[]. 是一个长度可变的容器.
 * Collection : 保存一个一个的对象
 *      无序可重复. 无序 : 不按添加顺序保存元素, 可重复 : 重复的对象可以多次添加.
 *      boolean add(Object obj) 添加元素, 返回值表示添加成功或失败
 *      boolean contains(Object obj) 判断当前集合中是否包含参数中的对象
 *      boolean remove(Object obj) 删除指定的元素
 *      int size() 返回元素个数
 *
 *      Set : 保存一个一个的对象, 无序不可重复
 *          HashSet : 使用哈希算法实现的Set集合.
 *              去重规则 : 两个对象的equals为true, 两个对象的hashCode也必须相等.
 *
 *          TreeSet : 基于二叉搜索树实现的Set集合. 内部要实现自然排序, 如果提供了比较器,它就会定制排序.
 *              去重规则 : 两个对象的compare为0.
 *
 *      List : 保存一个一个的对象, 有序可重复
 *          void add(int index, Object ele). 在指定下标位置处插入新元素
 *          Object get(int index) 返回指定下标处的元素
 *          Object remove(int index) 删除指定下标处的元素
 *          Object set(int index, Object ele) 替换指定下标处的元素为参数ele. 旧元素作为返回值.
 *
 *          ArrayList : 基于数组实现的List集合
 *          Vector : 和ArrayList等价.
 *          LinkedList : 基于链表实现的List集合.
 *
 * Map : 保存一对一对的对象
 *
 */

class Student implements Comparable {

    private int id;
    private String name;
    private int grade;
    private double score;

    public Student() {}

    public Student(int id, String name, int grade, double score) {
        this.id = id;
        this.name = name;
        this.grade = grade;
        this.score = score;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getGrade() {
        return grade;
    }

    public void setGrade(int grade) {
        this.grade = grade;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", grade=" + grade +
                ", score=" + score +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id &&
                grade == student.grade &&
                Double.compare(student.score, score) == 0 &&
                Objects.equals(name, student.name);
    }

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

    @Override
    public int compareTo(Object o) throws RuntimeException {
        if (!(o instanceof Student)) {
            throw new RuntimeException("对象不可比");
        }
        int n = (int)(this.score - ((Student)o).score);
        if (n == 0) {
            n = 1;
        }
        return n;
    }

}

// 写一个比较器, 用于完成两个学生对象的比较
class MyComparator implements Comparator {

    @Override
    public int compare(Object o1, Object o2) {
        if (!(o1 instanceof Student) || !(o2 instanceof Student)) {
            throw new RuntimeException("对象不可比");
        }
        return -(((Student)o1).getGrade() - ((Student)o2).getGrade());
    }
}

public class CollectionTest {

    @Test
    public void test7() {
        MyComparator myComparator = new MyComparator();
        Set set = new TreeSet(myComparator); // 通过构造器传递对象, 99.9%的情况是对象关联.
        Student s1 = new Student(1,"小明", 5, 80);
        Student s2 = new Student(2,"小花", 4, 90);
        Student s3 = new Student(3,"小伟", 2, 100);
        Student s4 = new Student(4,"小芳", 1, 90);
        Student s5 = new Student(5,"小丽", 6, 50);

        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);

        for (Object tmp : set) {
            System.out.println(tmp);
        }

        System.out.println("*************************************");
        // 1) 遍历谁, 就向谁要迭代器.
        Iterator iterator = set.iterator();
        // 使用注意事项1 : 迭代器要趁热使用
        // set.remove(s1); 不要随意再修改集合的内容, 否则迭代器会出问题.
        // 2) 循环依次询问当前游标后面有无元素, 如果有, 返回true
        while (iterator.hasNext()) {
            // 真的获取到后面的元素, 并且会引发内部游标的下移
            Object obj = iterator.next();
            // next()在循环中必须只调用一次.
            System.out.println(obj);
        }
        // 使用注意事项 : 迭代器是一次性使用, 用完作废.

    }

    @Test
    public void test6() {
        Set set = new TreeSet();
        Student s1 = new Student(1,"小明", 5, 80);
        Student s2 = new Student(2,"小花", 4, 90);
        Student s3 = new Student(3,"小伟", 2, 100);
        Student s4 = new Student(4,"小芳", 1, 90);
        Student s5 = new Student(5,"小丽", 6, 50);

        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);

        for (Object tmp : set) {
            System.out.println(tmp);
        }
    }

    @Test
    public void test5() {
        Set set = new TreeSet();
        //set.add(20);
        //set.add(5);
        //set.add(2);
        //set.add(10);
        set.add("cc");
        set.add("bb");
        set.add("aa");
        //set.add(30);

        for (Object tmp : set) {
            System.out.println(tmp);
        }
    }

    @Test
    public void test4() {
        Set set = new TreeSet();
        set.add(20);
        set.add(5);
        set.add(2);
        set.add(10);
        set.add(80);
        set.add(60);
        set.add(5);

        for (Object tmp : set) {
            System.out.println(tmp);
        }
    }

    @Test
    public void test3() {
        Set set = new HashSet(); // 无序不可重复
        Student s1 = new Student(1, "小明", 3, 80);
        Student s2 = new Student(2, "小丽", 2, 90);
        Student s3 = new Student(1, "小明", 3, 80);

        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s1);

        for (Object obj : set) {
            System.out.println(obj);
        }
    }

    // 创建一个List集合, 保存10个20以内的随机整数.
    @Test
    public void exer3() {
        List list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            int n = (int)(Math.random() * 20);
            list.add(n);
        }
        // 遍历
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
    }

    // 创建一个List集合, 保存10个20以内的随机整数, 不要重复的.
    @Test
    public void exer4() {
        List list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            int n = (int)(Math.random() * 20);
            if (list.contains(n)) {
                i--;
                continue;
            }
            list.add(n);
        }

        for (Object tmp : list) {
            System.out.println(tmp);
        }
    }

    @Test
    public void exer42() {
        List list = new ArrayList();
        while (list.size() != 10) {
            int n = (int)(Math.random() * 20);
            if (!list.contains(n)) {
                list.add(n);
            }
        }

        for (Object tmp : list) {
            System.out.println(tmp);
        }
    }

    @Test
    public void exer43() {
        List list = new ArrayList();
        for (int i = 0; i < 10;) {
            int n = (int)(Math.random() * 20);
            if (!list.contains(n)) {
                list.add(n);
                i++;
            }
        }

        for (Object tmp : list) {
            System.out.println(tmp);
        }
    }

    @Test
    public void test2() {
        List list = new ArrayList();
        list.add("abc");
        list.add("yyy");
        list.add(new Integer(200));
        list.add("abc");
        list.add(200);
        list.add(new Student(2, "小丽", 1, 50));
        System.out.println(list);
        list.add(2, "我是汉字"); // 插入
        list.add(1, 3);
        System.out.println(list);
        Object o = list.get(7);
        System.out.println(o);
        list.remove(3); // 整数会优先作为下标来使用
        list.remove(Integer.valueOf(3)); // 删除对象
        System.out.println(list); //[abc, yyy, 200, abc, 200, Student{id=2, name='小丽', grade=1, score=50.0}]
        list.set(3, 3.14); // 替换操作
        System.out.println(list);
        System.out.println("*************************************");
        for (int i = 0; i < list.size(); i++) {
            Object o1 = list.get(i);
            System.out.println(o1);
        }

    }

    // 创建一个Set集合, 保存10个20以内的随机整数.
    @Test
    public void exer1() {
        Set set = new HashSet();
        for (int i = 0; i < 10; i++) {
            set.add((int)(Math.random() * 20));
        }
        // 遍历集合
        for (Object tmp : set) {
            System.out.println(tmp);
        }
    }
    // 创建一个Set集合, 保存10个20以内的随机整数. 保证10个.
    @Test
    public void exer12() {
        Set set = new HashSet();
        while (set.size() != 10) {
            set.add((int)(Math.random() * 20));
        }
        // 遍历集合
        for (Object tmp : set) {
            System.out.println(tmp);
        }
    }

    @Test
    public void exer13() {
        Set set = new HashSet();
        for (int i = 0; i < 10; i++) {
            int n = (int)(Math.random() * 20);
            if (!set.add(n)) {
                i--;
            }
        }
    }

    @Test
    public void exer14() {
        Set set = new HashSet();
        for (int i = 0; i < 10; ) {
            int n = (int)(Math.random() * 20);
            if (set.add(n)) {
                i++;
            }
        }
    }

    public static void main(String[] args) {
        Set set = new HashSet(); // Set : 无序不可重复
        set.add("abc");
        set.add("yyy");
        set.add(new Integer(200));
        set.add(100); // set.add(Integer.valueOf(100));
        set.add(new Student(1, "小明", 2, 80));
        boolean b1 = set.add("yyy");
        boolean b2 = set.add(200);
        System.out.println(b1);
        System.out.println(b2);

        System.out.println(set.size());

        System.out.println(set);

        System.out.println("***************************************");
        // 遍历集合.
        for (Object tmp : set) {
            System.out.println(tmp);
        }

        boolean contains = set.contains(200); // 判断是否包含
        System.out.println("contains = " + contains);

        set.remove(100); // 删除

        System.out.println(set);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值