JAVA集合框架

1.集合框架

集合框架是一个用来代表和操纵集合的统一架构(java集合框架位于java.util包中)
例如数组

  1. 数组定容(一组数组定义好,它的长度就无法改变),如果需要改变数组的长度,就变得很复杂。
  2. 我们需要定义一个灵活的数组,可以随意改变长度。

代码实例

import java.util.Arrays;

/**
 * @author:hzk
 * @date 2022/4/15 18:46
 */
public class MyArry {
    private Object[] arr;//声明一个Object类型的数组
    private int size;//定义数组下标,默认值为0

    public MyArry() {
        this(4);//调用有参构造MyArry(int intSzie)
    }
    public MyArry(int intSzie) {//intSize表示数组的长度
        if(intSzie<0){
            throw new RuntimeException("数组的长度出错");
        }
        arr = new Object[intSzie];
    }
    public void addData(Object o){//将元素o放入数组中
    //判断放入的数据是否超过数组的长度,超过则对数组进行扩容
        if(size>= arr.length){
            Object[] newArr = Arrays.copyOf(arr,size*2);
            arr = newArr;
        }
        arr[size] = o;
        size++;
    }
    public Object getData(int index){//获取指定数组的元素
        if (index>size){
            throw new ArrayIndexOutOfBoundsException("下标越界");
        }
        Object o =arr[index];
        return o;
    }
}

2.集合的框架

在这里插入图片描述

3.List集合-ArrayList

在这里插入图片描述

3.1创建集合对象

/**
 * @author:hzk
 * @date 2022/4/15 22:13
 */
public class Test1 {
    public static void main(String[] args) {
        List l = new ArrayList();
        List l1 = new ArrayList();
    }
}

3.2增删改查操作

 List l = new ArrayList();
        List l1 = new ArrayList();

        l.add("我");
        l.add("爱");
        l.add("java");
        l.add(1,"特别");//在下标为1的地方插入
        l.add("true");
        l.add(new Date());
        l1.addAll(l);
        System.out.println(l+"  "+l1);//打印时默认调用toString()

代码结果
[我, 特别, 爱, java, true, Fri Apr 15 22:18:22 CST 2022] [我, 特别, 爱, java, true, Fri Apr 15 22:18:22 CST 2022]

 l.remove("java");
        l.remove(0);
        System.out.println(l);
        l.clear();
        System.out.println(l);

代码结果
[特别, 爱, true, Fri Apr 15 22:22:25 CST 2022]
[]

 l.set(0,"可能");
        System.out.println(l);

代码结果
[特别, 爱, true, Fri Apr 15 22:24:16 CST 2022]
[可能, 爱, true, Fri Apr 15 22:24:16 CST 2022]

package com.qy1510415;

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

/**
 * @author:hzk
 * @date 2022/4/15 22:25
 */
public class Test2 {
    public static void main(String[] args) {
        List l = new ArrayList();
        l.add("我");
        l.add("要");
        l.add("好好");
        l.add("学");
        l.add("JAVA");
        Object s = l.get(3);
        System.out.println(s);//根据下标获取元素
        System.out.println(l.size());//获取集合长度
        boolean f =l.contains("学");
        System.out.println(f);//判断集合中是否包含该元素
        int index = l.indexOf("要");
        System.out.println(index);//查询元素第一次出现的位置
        //遍历集合内的元素
        for (int i=0;i<l.size();i++){
            System.out.print(l.get(i)+"  ");
        }
        //遍历集合内的元素
        for (Object n:l){
            System.out.print(n+" ");
        }
    }
}

代码结果:

5
true
1
我 要 好好 学 JAVA 我 要 好好 学 JAVA

3.3ArrayList底层源码

构造一个数组

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

加法

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 数组扩容
        elementData[size++] = e;//把元素赋到对应位置
        return true;
    }

判断元素第一次出现的位置

 public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

数组的长度

public int size() {
        return size;
    }

判断元素是否在集合中

public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

获取指定位置的元素

public E get(int index) {
        rangeCheck(index);//判断下标

        return elementData(index);
    }
     E elementData(int index) {
        return (E) elementData[index];
    }

为什么会打印对象的元素

public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

3.4LinkedList

它是一个链表结构
加法操作

  LinkedList l = new LinkedList();
        l.add("java");
        l.add("学习");
        l.add("好");
        l.add("true");
        System.out.println(l);
        l.addFirst("爱");
        l.addLast(new Date());
        System.out.println(l);

代码结果
[java, 学习, 好, true]
[爱, java, 学习, 好, true, Sat Apr 16 09:58:20 CST 2022]
删除操作

 l.remove("好");
        l.removeFirst();
        l.remove(0);
        System.out.println(l);

代码结果
[学习, true, Sat Apr 16 10:00:17 CST 2022]
修改操作

 l.set(0,"我爱学习");
        System.out.println(l);

代码结果
[我爱学习, true, Sat Apr 16 10:01:50 CST 2022]
查询操作

 System.out.println(l.size());
        System.out.println(l.contains("我爱学习"));
        System.out.println(l.getFirst());
        System.out.println(l.get(2));

代码结果
3
true
我爱学习
Sat Apr 16 10:04:43 CST 2022

3.4.1LinkedList底层源码

1.凡是查新源码,我们都是从类的构造方法入手:

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }

该类的构造方法内是空的,没有代码,但是该类中有三个属性,是通过接口t继承的

 implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;//索引
    transient Node<E> first;//第一个对象
    transient Node<E> last;//最后一个对象
  }

=add源码E可理解为Object类型===

public boolean add(E e) {
        linkLast(e);
        return true;
    }
    	
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

=Node源代码====

private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

代码执行过程
在这里插入图片描述

get获取元素===

 public E get(int index) {
        checkElementIndex(index);//检查下标是否正确
        return node(index).item;//返回该下标上的元素
    }

=Node===

Node<E> node(int index) {
        
		//>> 位运算二进制运算 ----- size >> 1 一半的意思size/2
        if (index < (size >> 1)) {//前半部分
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {//后半部分
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

4.Set集合

在这里插入图片描述

4.1HashSet集合

4.1.1创建HashSet对象

/**
 * @author:hzk
 * @date 2022/4/17 10:20
 */
public class Test1 {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        HashSet hashSet1 = new HashSet(10);//初始容器的大小
        //loadFactor:--->0.7f 表示负载因子,当空间使用70%时,要求扩展
        HashSet hashSet2 = new HashSet(10,0.7f);
    }
}

4.1.2添加元素

/**
 * @author:hzk
 * @date 2022/4/17 10:20
 */
public class Test1 {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        HashSet hashSet1 = new HashSet(10);//初始容器的大小
        //loadFactor:--->0.7f 表示负载因子,当空间使用70%时,要求扩展
        HashSet hashSet2 = new HashSet(10,0.7f);
        hashSet.add("我爱");
        hashSet.add("学习");
        hashSet.add("java");
        hashSet1.add("123");
        hashSet1.add("456");
        hashSet1.add("java");
        hashSet1.addAll(hashSet);
        System.out.println(hashSet1);//元素不重复且无序。
    }
}

代码结果
[学习, 123, java, 456, 我爱]

4.1.3删除

  hashSet1.remove("456");
        System.out.println(hashSet1);
        hashSet1.clear();
        System.out.println(hashSet1);

代码结果
[学习, 123, java, 456, 我爱]
[学习, 123, java, 我爱]
[]

4.1.4判断

  boolean empty = hashSet1.isEmpty();
        System.out.println(empty);
        boolean b = hashSet1.contains("学习");
        System.out.println(b);

代码结果
false
true

4.1.5hashSet遍历

(1)通过for each

for (Object o :hashSet1){
            System.out.print(o+"  ");
        }

(2)通过迭代器

 Iterator iterator = hashSet1.iterator();//获取迭代器对象,有序:有下标
        while (iterator.hasNext()){//判断指针是否能移动
            Object next = iterator.next();//获取指针指到的元素并获取
            System.out.println(next);
        }

代码结果
学习
123
java
我爱
在这里插入图片描述

4.1.6hashSet源码

    /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * default initial capacity (16) and load factor (0.75).
     */
    public HashSet() {
        map = new HashMap<>();
    }

4.2TreeSet集合

TreeSet中的方法和HashSet中的方法一模一样,只是它们的实现不一样。
TreeSet基于TreeMap实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。
存储String类型

public class Test2 {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet();
        treeSet.add("s1");
        treeSet.add("s2");
        treeSet.add("s3");
        treeSet.add("s4");
        System.out.println(treeSet);

    }
}

存储对象类型

TreeSet treeSet1 = new TreeSet();
        treeSet1.add(new Studnet("后裔",21));
        treeSet1.add(new Studnet("李白",20));
        treeSet1.add(new Studnet("廉颇",19));
        treeSet1.add(new Studnet("鲁班",18));
        treeSet1.add(new Studnet("嫦娥",19));
        treeSet1.add(new Studnet("la",17));
        treeSet1.add(new Studnet("ps",16));
        System.out.println(treeSet1);

此时 TreeSet中的元素必须实现Comparable接口 方可放入TreeSet

/**
 * @author:hzk
 * @date 2022/4/17 11:11
 */
public class Studnet implements Comparable {
    String name;
    int age;

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

    @Override
    //排序:---返回如果大于0 表示当前元素比o大  如果返回-1 当前添加的元素比o小  返回0表示相同元素。
    public int compareTo(Object o) {
        Studnet studnet = (Studnet) o;
        System.out.println(this+"对比"+o);
        if(this.age>studnet.age){
            return 1;
        }else if (this.age<studnet.age){
            return -1;
        }
        return 0;
    }

    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 "Studnet{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在创建TreeSet时,为其指定排序得规则。
TreeSet treeSet=new TreeSet();但是在创建对象时,并没有为其指定排序得规则,那么就要求该集合得元素有序规则,如果元素得类已经创建完成,不能修改该类得源码,这时就需要你在创建TreeSet时指定排序得规则,

/**
 * @author:hzk
 * @date 2022/4/18 20:56
 */
public class Test1 {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet(new MyComparator());
        treeSet.add(new Student("李白",15));
        treeSet.add(new Student("杜甫",16));
        treeSet.add(new Student("小飞",17));
        treeSet.add(new Student("小白",19));
        System.out.println(treeSet);
    }
}
class Student{
    String name;
    int age;

    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 +
                '}';
    }
}
/**
 * @author:hzk
 * @date 2022/4/18 21:01
 */
public class MyComparator implements Comparator {


    @Override
    public int compare(Object o1, Object o2) {
        Student student = (Student) o1;
        Student student1 = (Student) o2;
        if(student.getAge()>student1.getAge()){
            return 1;
        }else if (student.getAge()<student1.getAge()){
            return -1;
        }
        return 0;
    }
}

5.Map键值对模式

1.map中得每个元素属于键值对模式,如果往map中添加元素时,需要添加key和value。它也属于一个接口,该接口常见得实现类有:HashMap。

5.1如何创建Map对象

  //默认初始化大小为16,负载因子为0.75
        Map map = new HashMap();
        //初始化大小
        Map map1 = new HashMap(16);
        //初始化大小,负载因子
        Map map2 = new HashMap(16,0.75f);

5.2添加操作

public class Test2 {
    public static void main(String[] args) {
        //默认初始化大小为16,负载因子为0.75
        Map map = new HashMap();
        //添加操作 key:name  value:李白 key不能重复,会把前面相同的覆盖掉,但value不会
        map.put("name","李白");
        map.put("age",15);
        Map map1 = new HashMap();
        map1.put("k1","v1");
        map1.putAll(map);
        System.out.println(map1);
    }
}

5.3删除操作

map1.remove("name");
        System.out.println(map1);
        map1.clear();
        System.out.println(map1);

5.4修改操作

 map1.replace("name","赵云");
        System.out.println(map1);

5.5查询

/**
 * @author:hzk
 * @date 2022/4/18 22:13
 */
public class Test3 {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("k1","v1");
        map.put("k2","v2");
        map.put("k3","v3");
        map.put("k4","v4");
        boolean f = map.containsKey("k1");//判断是否存在指定的key
        System.out.println(map.get("k2"));//获取指定key的value
        Set keys = map.keySet();//返回map中所有key
        System.out.println(keys);
        for (Object n:keys){
            Object o = map.get(n);
            System.out.println(n+"  "+o);
        }
    }
}

5.6HashMap底层原理

JDK1.8 HashMap原理,存储元素使用的put(key,value).根据key的hash计算出相应的哈希值,根据相应的算法求出该元素在数组中的位置,如果求出的哈希值相同,则称为哈希冲突,会根据equals来判断元素是否一致,如果equals不同,则存入单向链表上,如果哈希碰撞的个数超过8个,则把链表转换为红黑二叉树。
JDK1.7和JDK1.8是有区别的。
前者使用的数据结构:数组+链表 而且链表插入模式为头部插入(造成死循环)
后者使用的数据结构:数组+链表+黑红树 而且链表的插入模式为尾部插入。

从构造器函数入口:

    /**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                //如果key的hash值相同,判断key的equals是否相同,替换原来的元素。
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        //判断链表的长度是否超过8个
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        //把链表转换为红黑树结构
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值