集合框架(Set Map List)

1.内存层面需要针对多个数据进行存储。此时,可以考虑的容器有数组、集合类

2.数组存储多个数据方面的特点

数组一旦初始化,其长度就是确定的。
数组中的多个元素是依次紧密排列的,有序的,可重复的。
(优点)数组一旦初始化完成,其元素的类型就是确定的

int[] arr=new int[10];
arr[0]=1;
arr[1]="AA";//编辑报错
Object[] arr1 =new Object[10];
arr[0] = new String();
arr[1]=new Date();

(优点)元素的类型既可以是基本数据类型,也可以是引用数据类型。

数组的存储多个数据的方式的弊端

数组一旦初始化,其长度就是不可变的
数组中存储数据特点的单一性。对于无序、不可重复的场景的多个数据加无能为力了
数组中可用的方法、属性都是极少的。具体的需求,都需要自己组织相关的代码逻辑。
针对于数组中元素的删除、插入操作、性能较差

 3.Java集合框架体系(java.util包下)
  java.util.Collection:存储一个一个的数据
      |----子接口:List:存储有序、可重复的数据("动态"数组)
           |---   ArrayListLinkedListVector
      |----子接口: Set:存储无序、不可重复的数据(高中学习的集合)
             |--- HashSetLinkedHashSetTreeSet
  java.util.Map:存储一对一对的数据(key-value键值对,(x1,y1),(x2,y2)-->y=f(x),类似于高中的函数) 不同key可以指向相同value,一个value不能对应多个key
             |--- HashMapLinkedHashMapTreeMapHashtableProperties**

1.常用方法:(Collection中定义了15个抽象方法。)
add(Object obj):添加元素对象到当前集合中
addAll(Collection coll):添加other集合中的所有元素对象到当前集合中

//addAll是把每个元素看成一个整体 coll.addAll(coll1);
//add   是把添加的全部看成一个整体 coll.add(coll1);

​ clear():清空集合元素
​ isEmpty():判断当前集合是不是为空集合
​ size():获取当前集合中实际存储的元素个数
​ contains(Object obj):判断当前集合中是否存在一个与obj对象equals返回true的元素
​ containsAll(Collection coll):判断coll集合众多元素是否在当前集合中都存在
​ retainAll(Collection coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保存两个相同的元素
​ remove(Object obj):当前集合中删除第一个找到的与obj对象equals返回true的元素
​ removeAll(Collection coll):从当前集合中删除所有与coll集合相同的元素
​ hashCode():哈希值
​ equals(Object obj):判断当前集合与obj是否相等
​ toArray():输出


​ iterator():迭代器

String arr []=new String[]{"AA","BB","CC"};
//数组转集合	
Collection list = Arrays.asList(arr);
System.out.println(list);
//集合转数组
Object [] array=list.toArray(arr);
//遍历
System.out.println(Arrays.toString(array));
Integer arr1[]=new Integer[]{1,2,3};
//数组转集合
List list1 = Arrays.asList(arr1);  //这边看成了三个对象
System.out.println(list1.size());//3

int arr2[]=new int[]{1,2,3}; //这边就是一个数组
List list2 = Arrays.asList(arr2);
System.out.println(list2.size());//1

向Collection中添加元素的要求:
要求元素所属的类一定要重写equals()

原因:因为Collection中的相关方法(比如:contains()/ remove()) 在使用时,要调用元素所在类的equals()。

1.迭代器的作用:用来遍历元素的

@Test
    public  void test7(){
        Collection coll=new ArrayList();
        coll.add("A");
        coll.add("B");
        coll.add(new Person("SYH",18));
        Iterator iterator = coll.iterator();
       while(iterator.hasNext()){
           System.out.println(iterator.next());
       }
       //增强for循环(针对于集合来讲,增强for循环的底层仍然使用的是选代器。)
        for(Object obj:coll){
            System.out.println(obj);
        }
        int[] arr1 =new int[]{11,22,33};
        for (int i:arr1){
            System.out.println(i);
        }
        String [] arr2=new String[]{"11","22","33"};
        for (String s:arr2){
            System.out.println(s);
        }
        
        //但是增强for不能用来赋值,因为底层是迭代器
         for (String s:arr2){
         		s="MM";
        }
    }

4.2 List接口方法

List除了从Collction集合继承的方法外,List 集合里添加了一些根据索引 来操作集合元素的方法。

  • 插入元素

  • void add(int index, Object ele):在index位置插入ele元素

  • boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来

  • 获取元素
    Object get (int index):获取指定index位置的元素

  • List subList(int fromlndex, int tolndex):返回从fromlndex到tolndex位置的子集合

  • 获取元素索引
    int indexOf(Object obj):返回obj在集合中首次出现的位置

    int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置

  • 删除和替换元素

    object remove(int index):移除指定index位置的元素,并返回此元素

    Object set(int index, Object ele) :设置指定index位置的元素为ele

    小结:

    ​ 增

    ​ add(Object obj)

    ​ addAll(Collection coll)

    ​ 删

    ​ remove(Object obj). remove(Integer.valueof(2) ) //删除数据2

    ​ remove(int index).

    ​ 改

    ​ set(int index,Object ele)

    ​ 查

    ​ get(int index)

    ​ 插

    ​ add(int index,Object elements)

​ addAll(int index, Collection eles)

​ 长度

​ size()

​ 遍历

​ iterator() :使用迭代器

​ for() 一般/增强for循环

List及其实现类的特点

java.util.Collection:存储一个一个的数据

​ |-----子接口:List:存储有序的、可重复的数据("动态"数组)

​ |----ArrayList:List的主要实现类;线程不安全、效率高、底层使用Object[]数组存储(大部分情况用,查询时候是o(1))

​ 在添加、查找数据,效率较高,在插入删除时, 效率较低

​ |----Vector:List古老的实现类;线程安全的、效率低:底层使用Object[]数组存储

​ |----LinkedList:底层使用双向链表的方式进行存储;在对数据进行频繁的删除插入操作使用此类

​ 在添加、查找数据,效率较低,在插入删除时, 效率较高

Set及其实现类的特点

java.util.Collection:存储一个一个的数据

​ |----子接口: Set:存储无序、不可重复的数据(高中学习的集合)

​ |— HashSet(主要实现类)底层使用的是hashSet(数组+单向链表+红黑树结果进行存储在JDK8中,之前没有红黑树)

​ |—LinkedHashSet:是hashSet 的子类;在现有的结构基础上,有添加了一组双向链表,用于记录添加元素的先后顺序,即可以按照添加元素的先后顺序进行遍历。便于频繁的查询操作

​ |—TreeSet:底层使用红黑树存储。可以按照添加的元素指定属性的大小顺序进行遍历

2.开发中的使用频率场景

​ 较List、Map,Set使用较少

​ 用来过滤重复数据

3.Set中常见方法:即为Connection中声明的十五个抽象方法。没有新增的方法。

4.Set中无序性、不可重复性的理解(以HashSet及其子类为例说明)

无序性!=随机性。

​ 添加元素的顺序和遍历元素的顺序不一致,是不是就是无序性呢?不是

​ 什么是无序性?与添加元素的位置有关。不像ArrayList一样是依次紧密排列的。

​ 根据添加的元素哈希值计算数组中的位置。此顺序不是依次排列的,表现为无序性

不可重复性:添加set的元素是不能相同的。需要判断hashcode()得到的哈希值与equals()得到的boolean结果(若equal()相同和hash值相同都为true,则元素相同,反之亦然)

5.添加hashSet/LinkedHashSet中的元素要求:

​ 要求元素所在的类重写两个方法:equals()和hashCode()

​ 同时要equals()和hashcode()要保持一致性,需要在IDEA中自动生成两个方法的重写即可,保证两个方法的一致性,先看hash再看equals()
6.TreeSet的使用

6.1底层的数据结构:红黑树

6.2添加元素的特点:可以按照添加的元素指定属性的大小顺序进行遍历,否则会报ClassCase(里面的元素类型要一样)

​ TreeSet比较跟hashSet/LinkedHashSet不一样的点是 比较的时候不是看hashcode和equals看的是compareTo方法,比较的类要继承Comparabe接口

6.3向TreeSet中添加的元素的要求

​ 要求添加到TreeSet中的元素必须是用一个类型的对象,否则会报ClassCastException

​ 添加的元素需要考虑排序:1自然排序 2定制排序

6.4判断数据是否相同的标准

​ 不再是考虑hashCode()和equals()方法了,也就意味着添加到TreeSet中的元素所在的类不需要重写hashCode()和equals()方法
比较元素大小或比较元素是否相等的标准考虑自然排序或定制排序中,CompareTo()或compare()的返回值(implement Comparable),如果compareTo()或compare()的返回值为0,则认为两个对象相等的。由于TreeSet中不能存放相同的元素,则后一个相等的元素就不能添加到TreeSet中。

一种比较方法 匿名 (定制排序)

@Test
public void test3(){
    Comparator comparator=new Comparator() {
        /**
         *
         * 按照姓名从大到小排列,如果姓名相同,继续比较age,按照从大到小排列
         * @param
         */
        @Override
        public int compare(Object o1, Object o2) {
            if(o1 instanceof User && o2 instanceof User ){
                User u1=(User)o1;
                User u2=(User)o2;
                int value= u1.getName().compareTo(u2.getName());
                if(value !=0){
                    return value;
                }
                return -(u1.getAge()-u2.getAge());
            }
            throw new RuntimeException("类型不匹配");
        }
    };
    TreeSet TreeSet=new TreeSet(comparator);
    User user1=new User("Tom",23);
    User user2=new User("Jerry",43);
    User user3=new User("Rose",21);
    User user4=new User("Jack",23);
    User user5=new User("Tony",33);
    TreeSet.add(user1);
    TreeSet.add(user2);
    TreeSet.add(user3);
    TreeSet.add(user4);
    TreeSet.add(user5);
    for (Object o:TreeSet){
        System.out.println(o.toString());
    }
}

一种在类内部重写compareTo(自然排序)

package com.set;

import java.util.Objects;

/**
 * @Author Tom
 * @Date 2023/12/25 10:53
 * @Description: User
 */
public class User implements  Comparable {
   private String  name;
   private int age;
    public User(){
    }
    public User(String name,int age){
        this.name=name;
        this.age=age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("User 的 equals()方法");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name,age);
    }
    /**
     *先比较年龄从小到大排列,如果年龄相同,则继续比较姓名从小到大
     */
    @Override
    public int compareTo(Object o) {
        if (this == o) return 0;
        if (o instanceof User){
            User u=(User) o;
            int value= this.age-u.age;
            if (value!=0){
                return value;
            }
            return this.name.compareTo(u.name); //从小到大按照名字
            //return -this.name.compareTo(u.name); //从大到小按照名字
        }
        throw  new RuntimeException("类型不匹配");
    }

    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;
    }
}

1.Map及其实现类对比

java.until.Map:存储一对一对的数据(key-value键值对,(x1,y1)、(x2,y2) --> y=f(x),类似于高中的函数)

​ |----HashMap:主要实现类,线程不安全的,效率高;可以添加null的key和value值;底层使用数组+单向链表+红黑树(JDK8,JDK8之前没有红黑树)

​ |—LinkedHashMap;是hashMap的子类;在HashMap的数据结构基础上,增加了一对双向链表,用于记录添加的元素顺序先后

​ 因为使用双向循环链表,进而遍历元素时,可以按照添加的顺序显示

​ 开发中,对于频繁的遍历操作,见识使用此类

​ |----TreeMap:底层使用红黑树存储,按照添加的key-value中的key元素的指定的属性的大小顺序进行排序

​ 需要考虑,自然排序,定制排序

​ |----Hashtable:古老实现类,线程安全的,效率低;不可以添加null的key和value值(数组+单向链表)

​ |—Properties:其key和value都是String类型,常用来处理属性文件
2.hashMap中元素的特点

hashMap中的所有的key彼此之间是不可重复、无序的。所有的key构成一个hashSet集合–>key所在的类要重写hashCode()和equals()方法

hashMap中的value彼此之间是可重复无序的,所有的key构成一个Collention集合–>value所在的类要重写equals();

hashMap中的一个key-value,就构成了一个entry

hashMap中的所有entry彼此之间是不可重复、无序的。所有的entry就构成了一个Set集合。

如果key一样 value不一样 会覆盖 所以 Map里的put 可以添加也可以修改!!
3.Map中的常用方法

-添加、修改操作:

​ -Object put(Object key,Object value);将指定key-value添加到(或修改)当前map对象中

​ -void putAll(Map m):将m中的所有key-value对存放到当前map中

-删除操作:

​ -Object remove(Object key):移除指定key的key-value对,并返回value

​ -void clear():清空当前map中的所有数据

-元素查询的操作:

​ -Object get(Object key):获取指定key对应的value

​ -boolean containsKey (Object key):是否包含指定的key

​ -boolean containsValue(Object value):是否包含指定的value

​ -int size():返回map中key-value对的个数

​ -boolean isEmpty():判断当前map是否为空

​ -boolean equals(Object obj):判断当前map和参数对象obj是否相等

-元视图操作的方法:
-Set keySet():返回所有key构成的Set集合

​ -Collection values():返回所有value构成的Collection集合

​ -Set entryset():返回所有key-value对构成的Set集合
小结:

增:

​ put(Object key,Object value)

​ Object remove(Object key)

​ put(Object key,Object value)

​ void putAll(Map m)

​ Object get(Object key)

长度

​ int size()

遍历

​ 遍历key集:Set keySet()

​ 遍历value集:Collection values()

​ 遍历entry集: Set entrySet()

@Test
public void test2(){
    //遍历key集:Set keySet()
    HashMap map=new HashMap();
    map.put("AA",56);
    map.put(67,"Tom");
    map.put("BB",78);
    map.put(new Person("Jerry",12),56);
    Set keySet=map.keySet();
    //使用迭代器 key
    Iterator iterator=keySet.iterator();
    while(iterator.hasNext()){
        System.out.println(iterator.next());
    }

    //遍历value
        Collection value=map.values();
        Iterator iterator1=value.iterator();
        while(iterator1.hasNext()){
            System.out.println(iterator1.next());
        }


      //遍历entry集: Set entrySet()
        Set entrySet=map.entrySet();
        //使用迭代器
        Iterator iterator=entrySet.iterator();
        while(iterator.hasNext()){
            Map.Entry entry=(Map.Entry)iterator.next();
            System.out.println(entry.getKey()+"---"+entry.getValue());
        }
        
        //这样也行
        Set set1= map.keySet();
        for (Object s:set1){
            System.out.println(s+" "+map.get(s));
        }
}

TreeMap的使用

底层使用红黑树存储。

可以按照添加的key-value中的key元素的指定的属性的大小顺序进行遍历

需要考虑使用1.自然排序 2.定制排序

要求:向TreeMap中添加的key必须是同一个类型的对象

5.Hashtable与Properties的使用

Properties:是hashtable的子类,其值key和value都是String类型,常用于处理属性文件

你可能感兴趣的:(JAVA,java,数据结构)