JAVA 集合(第十)

一、集合的框架(转载自

1、集合的概述

为了在程序中保存数目不确定的对象,java提供了一系列特殊的类,这些类可以存储任意类型的对象,并且长度可以改变,这些类都称为集合.集合类都位于JAVA。uti包中使用时必须导包。
可以大概分两类
COllection:单列集合的根接口
-------LIst、列表
--------------**ArrayList 、动态数组 ; LInkedList、链表数组;Vector **
-------Set、集合
--------------HashSet、哈希集合
----------------------------LinkedHashSet、链式散列集
--------------TreeSet、树集合

Map:双列集合类的根接口
-------HashTable、、哈希表
--------------Properties、、特性
-------HashMap、、哈希图
--------------LInkedHashMap、、
-------TreeMap、、矩形树图

2、为什么要集合框架

对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。数组无法满
足。 就使用集合容器进行存储。集合容器因为内部的数据结构不同,有多种具体容器。
不断的向上抽取,就形成了集合框架。
框架的顶层是Collection接口,定义了集合框架中共性的方法。
数组的插入删除速度太慢,查找速度比较快。
集合的插入删除速度比较快,查找慢。

3、Collection接口

Collection是所有单列集合的父接口,他定义啦单列集合(LIst和Set)通用的一些方法,这些方法可以操作所有的单列集合
实际开发很少用Collection ,更多的是用子接口的方法。
没有get
在这里插入图片描述

二、LIst接口(ArrayLIst重要)

-------LIst、列表
--------------**ArrayList 、动态数组 ; LInkedList、链表数组;Vector **

ArrayList集合

ArrayLIst的本质还是一个数组,不过是一个已经封装好的数组了,这个数组的长度可以可以改变,长度不够时,ArrayLIst会在内存中分配一个更大的数组来保存元素

特点:

因为ArrayLIst的长度改变方式的原因,所以效率比较低,因此不适合做大量的增加和删除操作,但是他允许通过索引的方式来访问元素,所以查找元素比较便捷。

创建和使用

public static void main(String[] args) {
    
    

       ArrayList list=new ArrayList ();//创建AeeayLIst类
}

常用方法

size() 数组中数据的个数并不是长度
方法名 含义
add() 追加
get(index) 根据下标获取值
isEmpty() 判断ArrayList中是否有数据
indexOf(数据 ) 获取aa在ArrayList中首次出现的索引,有返回,没有-1
lastIndexOf(数据) 返回数据最后一次出现的索引
contains(数据) 判断数据在ArrayList中是否存在
remove(index)/remove(obj) 根据下标删除,或者直接删除数据
toArray() 将List转换成数组
clear() 清空List列表
set(索引,“数据”) 将指定索引的数据修改

遍历

普通for

  //个数遍历size()
        for(int i=0;i<list.size();i++){
    
    
            System.out.println(list.get(i));
        }

增强for

//增强性for
        for (Object o : list) {
    
    
            System.out.println(o);
        }

迭代器

 //迭代器
        Iterator it=list.iterator();
        
        while (it.hasNext()){
    
    
            Object obj=it.next();//拿object这个类型的值可以接任何数据类型
            System.out.println(obj);
        }

底层(对数组的操作)

自己把着去看

泛型

LInkedLIst集合和vector

LinkedList:链表结构,有序,插入和删除速度快,遍历查找速度慢

   LinkedList list=new LinkedList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add("4");

        for(Object obj:list){
    
    
            System.out.println(obj+"\t");
        }

Vector:ArrayList和Vector实现原理都一样,ArrayList:线程不安全,效率高。

  Vector list=new Vector();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add("4");

        for(Object obj:list){
    
    
            System.out.println(obj+"\t");
        }

Vector:线程安全,效率低;

Iterator接口(也被称为迭代器)

专门用来遍历集合中所有元素集合的时候使用的方法

注意:迭代器获得的元素时,这些元素类型都是Object类型的,如果需要特定数据类型的时候需要强转。

 Iterator it=list.iterator();

        while (it.hasNext()){
    
    
            Object obj=it.next();//拿object这个类型的值可以接任何数据类型
            if(obj.equals(1)){
    
    //删除
                list.remove(obj);
                break;
            }
        }
        System.out.println(list);
返回类型 方法 描述
boolean hasNext() 如果有元素可迭代
Object next() 返回迭代的下⼀个元素

三、Set接口

Set集存储的顺序无序,不可以保存重复元素。
TreeSet是可以保持自然顺序或者定义的比较器的比较的结果顺序的set集合
是以二叉树的方式来存储元素可以实现对集合中的元素进行排序

LInkedHashSet维护一个双重列表,能保存添加是的顺序

1.HashSet类(底层是HashMap)

可以存储任意对象类型的数据 包括null
无序
数据不能重复 数据结构跟LIst不同
没有下标 查找慢,插入删除快。

在这里插入图片描述

2.HashSet的创建使用

public static void main(String[] args) {
    
    
        HashSet<Object> set = new HashSet<>();
        set.add(1);
        set.add("abc");
        set.add("你好哈哈哈");
        set.add(1);//数据不重复 会自动除重
        set.add("hello world");
        set.add("5sc");
        //使用迭代器遍历
        Iterator<Object> iterator = set.iterator();
        /*while (iterator.hasNext()){
            System.out.println(iterator.next());
        }*/
        //使用for each遍历
        for (Object o : set) {
    
    
            System.out.println(o);
        }
    }

3、常用方法

add:添加
clear:删除集合所有元素
clone:返回Hashset实例浅层副本 本身不被克隆
contains:判断是否有指定元素 有返回true;
isEmpty:判断集合不包含元素就返回true
iterator:迭代器
remove:删除
size:元素个数
spliterator 快速出击late-binding和故障快速Spliterator

4、iterator 迭代器

因为hashset没有下标 所以需要迭代器来使用
因为HashSet的内部数据结构是哈希表,线程是不安全的。为了保证对象元素的内容角度唯一,必须覆盖hashCode方法和equals方法。

5、TreeSet

基于TreeMap实现比较器
基本数据类型 按照默认的排序 ,和String类中重写了compareTo()方法定义了字符排序的规则。

默认按照元素自然排序,必须实现Comparable接口

有序;不重复;添加删除判断效率高;

TreeSet排序方式
1、如果是基本数据类型和String类型,可以直接进行排序
2、对象类元素排序,需要实现Comparable接口,并覆盖其compareTo方法
实现步骤:排序的类实现Comparable接口,重写compareTo方法,并在方法里定义排序规则
3、另一种对象类元素排序:需要实现Comparator接口,并覆盖其compare()方法。
创建比较器,实现comparator接口,重写compare方法,在方法里定义排序规则。

TreeSet:可以对set集合进行排序,线程不安全。

判断元素不重复方法是:根据比较方法的返回结果是否为0,如果是0,则是相同元素,不存,如果不是0,则是不同元素,存储。

注意:LinkedHashSet是一种有序的Set集合,即其元素的存入和输出的顺序是相同的。
案例 排序方法2

   public static void main(String[] args) {
    
    
        //comparable接口  并且要重写  compareTo()方法
        TreeSet<Student> students=new TreeSet<>();
        students.add(new Student("张三",18));
        students.add(new Student("张2",119));
        students.add(new Student("张1",189));
        students.add(new Student("张4",184));

        System.out.println(students);
    }
public class Student implements Comparable<Student>{
    
    
    private String name;
    private int age;

    public Student() {
    
    
    }

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

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

    @Override
    public int compareTo(Student o) {
    
    
        Student o1 = (Student) o;
        if(this.age>o1.age){
    
    
            return -1;
        }else if(this.age<o1.age){
    
    
            return 1;
        }else {
    
    
            return 0;
        }

    }
}

案例排序方法3
测试类

public static void main(String[] args) {
    
    
        //comparable接口  并且要重写  compareTo()方法
        PeoCompar student=new PeoCompar();
        //创建一个比较器对象
        TreeSet<Student> students=new TreeSet<>(student);
        students.add(new Student("张三",18));
        students.add(new Student("张2",119));
        students.add(new Student("张1",189));
        students.add(new Student("张4",184));
        for (Student stu:students){
    
    
            System.out.println(stu);
        }

比较器

public class PeoCompar implements Comparator {
    
    
    @Override
    public int compare(Object o1, Object o2) {
    
    
        //将数据强转成Student类型
        Student p1=(Student) o1;
        Student p2=(Student) o2;
        if(p1.getAge()>p2.getAge()){
    
    
            return -1;
        }else{
    
    
            return 1;
        }


    }
}

学生类

public class Student  {
    
    
    private String name;
    private int age;

    public Student() {
    
    
    }

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

    public void setAge(int age) {
    
    
        this.age = age;
    }

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

二维数组

   public static void main(String[] args) {
    
    
        ArrayList arrayList=new ArrayList();
        //String[][] ints=new String[9][];
        //list嵌套list
        for (int i=0;i<9;i++){
    
    
            List list=new ArrayList<>();
            for (int j=0;j<=i;j++){
    
    
                list.add((i+1)+"*"+(j+1)+"="+(i+1)*(j+1));//给数组赋值
            }
            arrayList.add(list);
        }
        for (int i=0;i< arrayList.size();i++) {
    
    
            List list=(List) arrayList.get(i);
            for (int j=0; j < list.size(); j++) {
    
    
                System.out.print(list.get(j) + "\t");
            }
            System.out.println();
        }
        }

四、MAP接口

Map是一种双列集合,他的每个元素都包含一个 键对象key,一个值对象value,key和value是一种对应关系,称为映射,通过找键就能知道值value

key和value可以是任意数据类型,key具有唯一性,value可以重复
Map 存储的是键值对 类似JSON的对象

1、HashMap集合

是MAP接口的实现类,用于存储键值对的映射关系,没有重复键,键值对没有顺序
如果添加重复的key,后⾯的覆盖前⾯的。

2、创建使用

属性名:属性值,key:value。
增加 put
删除 remove
修改 put

遍历
1、遍历values 值 无序
2、遍历key
3、遍历节点对象entry

  public static void main(String[] args) {
    
    
        //声明一个列表存储多个学生
        //每行信息存储多个相同信息还是用list

        //声明一个对象 存储一个学生对象  项姓名  年龄
        HashMap map=new HashMap();
        map.put("name","张三");
        map.put("age",11);
        System.out.println(map.get("name"));//根据key name 获取 姓名//张三

        HashMap map1=new HashMap();
        map1.put("name","张2");
        map1.put("age","33");
        System.out.println(map1.get("age"));//33
        /* Map *///遍历
        Collection values = map1.values();
        for(Object obj: map.keySet()){
    
    
            System.out.println(obj+"\t");//张三//11
        }//无序的 key
        System.out.println("+++++");
        Set set=map.keySet();
        for (Object key:set){
    
    
            System.out.println(key+"---"+map.get(key)+"\t");//name---张三//age---11	
           //Map  遍历节点对象
        Set<Map.Entry> entrys=map.entrySet();
        for (Map.Entry entry:entrys){
    
    
            System.out.println(entry.getKey()+"===="+entry);
            //name====name=张三  age====age=11

        }
        }
    }

3、底层

HashMap的底层结构实际上是“链表散列”,即数组和链表的结合体。
HashMap的put和get的实现

put(key,value)原理

先将key和value封装到一个对象里面 ,
然后调用hashCode方法求出hash值,通过哈希表函数/哈希算法,将hash值转换成数组的下标,判断该位置上是否已有元素,如果已经有元素存在,则遍历该Entry[]数组位置上的单链表。判断key是否存在(equals判断),如果key已经存在,则用新的value值,替换点旧的value值,并将旧的value值返回。如果key不存在于HashMap中,程序继续向下执行。将key-vlaue, 生成Entry实体,添加到HashMap中的Entry[]数组中。

get(key)原理

在get方法中,首先通过hashCode方法计算hash值,然后调用indexFor()方法得到该key在table中的存储位置(下标),得到该位置的单链表(如果这个位置什么的没有返回null),遍历列表找到key和指定key内容相等的Entry(equals方法)(如果equals都返回fals,get返回一个null,),返回entry.value值。

4、哈希表 HashTable

哈希表是根据设定的哈希函数H(key)和处理冲突方法将一组关键字映射到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种表称为哈希表或散列,所得存储位置称为哈希地址或散列地址。作为线性数据结构与表格和队列等相比,哈希表无疑是查找速度比较快的一种。

不允许空key null不能
key无序 linkedHashMap是有序的

TreeMap是自然序

HashTable是线程不安全的 ConcurrentHashMap:是线程安全

5、HashMap和HashTable的区别

1、HashTable是线程安全的,HashMap是线程不安全的
Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合。{ 来源}
2、HashMap可以用null来做key HashTable不可以(尽量别用)
3、HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类。
4、容量
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
HashMap扩容时是当前容量翻倍即:capacity2,Hashtable扩容时是容量翻倍+1即:capacity2+1。

Properties

这个类:可以当成map用
在这里插入图片描述
在这里插入图片描述

嵌套

泛型

概念

什么是泛型 E:泛型的一个占位符 数据类型的代指-----参数化数据类型
意思是我传递啦一个数据类型
LIst list=newArrayList();
list.add(1);
泛型在编译阶段的一种特性 (运行阶段没有用)

泛型:参数化数据类型 ,写一个类的时候数据类型没有定死,声明的时候给这个占位符赋值

为什么用泛型

因为list中对存储的内容没有限制,所以取值需要强转,当使用泛型的时候就不需要强转了

1、规范数据类型的存储
2、避免了强转
3、只存在于编译期

public static void main(String[] args) {
    
    
        List<String> list=new ArrayList<String>();//限制了存储类型
        List<Integer> list1=new ArrayList<Integer>();

        list.add("sdf");//list类型是String
        list.add("3");
        list1.add(32);//list1类型是int类型
        System.out.println(list.get(1));
        for (String str:list){
    
    
            System.out.println(str);
        }
    }

自定义泛型类

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

注解(注释类型)

内置注解

注解 又被称为注释类型 Annotation
* 第一 语法格式 @注解类型名
* 第二 注解可以出现在类,属性上,方法上,变量上,
注解还可以出现在注释类型上
注解是引用数据类型 在这里插入图片描述

常见的注解

Dekprecated 注释的程序元素
Override 表示一个方法声明打算重写超类中的另一个方法声明
SuppressWarnings 指示应该在注释元素中取消显示指定的编译器警告

Override 在这里插入图片描述
Dekprecated

在这里插入图片描述

元注解
什么是元注解
用来注解 “注解类型的” 注解 被称为元注解
常见的元注解
在这里插入图片描述

Target 元注解
@Target(ElementType.METHOD) 表示这个注解只能出现在方法上面
用来指定被注解的注解可以出现的位置 在什么地方
在这里插入图片描述

REtention元注解

@Retention(RetentionPolicy.SOURCE)  //表示该注解保留在java源文件中。
@Retention(RetentionPolicy.CLASS)  //被保存在class文件中
@Retention(RetentionPolicy.RUNTIME) //保存在class文件中并且可以被反射方获取到

用来标注被“标注的注解”最终保留在什么地方
在这里插入图片描述

枚举

猜你喜欢

转载自blog.csdn.net/qq_45438019/article/details/119736015