集合框架的学习

阅读: 评论:0

集合框架的学习

集合框架的学习

目录

1、为什么使用集合?

2、集合架构有哪些?

3、List集合- ArrayList集合

4、LinkedList集合。

5、Set集合( HashSet集合)

6、TreeSet集合。

7、 Map

8、HashMap集合

9、TreeMap集合

 

1、为什么使用集合?

1. 我们原来讲过数组.思考: 数组有缺陷?--定容【一定数组定义好,他们得长度就无法改变.】如果需要改变数组得长度,变得很复杂。
​
2.我们是否可以定义一个长度改变的容器。---当然可以。
​
3.手撕可变长度的容器。
​
package com.ykq;
​
import java.util.Arrays;
​
/*** @program: day02* @description:* @author: 闫克起2* @create: 2022-04-15 14:13* //自定义可变长度的容器类。**/
public class MyArray {
​private Object [] arr; //声明一个Object类型的数组private int size;//表示数组的下标 因为他们是类成员变量 在创建对象时都有默认值。
​
​public MyArray(){ //无参构造函数this(3);  //本类中其他的构造函数 this本类的对象。 如果在构造方法中this()表示调用本类的其他构造函数}
​public MyArray(int initSize){ //有参构造函数--表示数组的长度if(initSize<0){ //长度不合法throw new RuntimeException("sorry 数组的长度有误。");}arr=new Object[initSize];}
​//把元素o放入数组arrpublic void addData(Object o){//判断你的数组是否已满if(size>=arr.length){//扩容--(1)容器的长度变长 (2)把原来容器中的元素复制到新的容器中Object[] newArr = pyOf(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;}
​
​
}

我们自己可以手写一个可变的容器,那么别人也可以手写可变的容器。

java官网 基于数组 根据不同的数据结构 创建了多个类 而这些类统称 为集合框架。

以后 我们在说集合框架时 就表示多个类。

2、 集合的架构

3、List集合-ArrayList集合

3.1 创建集合对象

   List list = new ArrayList(); //创建一个集合对象 如果没有指定集合容器的长度默认为10
​List list1 = new ArrayList(15); 

3.2 添加的操作

        //添加 (1)可以添加任意类型list.add("java01");list.add("java02");list.add(15.5);list.add(18);list.add(true);list.add(new Date());System.out.println(list);list.add(2,"hello"); //下标为2的位置添加元素 并把后面的元素进行唯一System.out.println(list); //打印一个对象时默认调用的为toString()
​List list2=new ArrayList();list2.add("a");list2.add("b");
​list.addAll(list2);//添加多个元素 把list2中的每个元素一一添加到list中System.out.println(list);

3.3 删除的操作

   //删除操作ve(2);//移除下标为2的元素System.out.println(list);list.clear();//清空集合中的元素.System.out.println(list);

3.4 修改的操作

        //修改操作list.set(1,"刘德华");System.out.println(list);

3.5 查询操作

List list = new ArrayList();list.add("java01");list.add("java02");list.add("java03");list.add("java02");
​//查询的方法Object o = (1);//根据下标获取元素System.out.println(o);
​int size = list.size();//获取集合中元素的个数。System.out.println(size);
​boolean f = ains("java05");//判断元素是否在集合中System.out.println(f);
​int index = list.indexOf("java05");//查询元素在集合中第一次出现的位置System.out.println(index);
​//遍历集合中的元素 for循环for(int i=0;i<list.size();i++){Object o1 = (i);System.out.println(o1);}

练习: 创建一个List的对象,并添加 删除 修改操作以及查找操作。

3.6 ArrayList底层源码

从构造方法来入手。new ArrayList(22) 底层声明了一个Object类型的数组 名字elementDataObject[] elementData
​public ArrayList(int initialCapacity) {if (initialCapacity > 0) { //大于0this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) { //等于初始化为一个空数组this.elementData = EMPTY_ELEMENTDATA;} else { //抛出一个异常throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}
​
==========add("java01")======E理解为Object类型================  public boolean add(E e) {ensureCapacityInternal(size + 1);  // 扩容 elementData[size++] = e;  //把元素赋值给数组的相应位置return true;}
==========indexOf("java02") 判断元素在集合中第一次的位置=============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;}   
​
===========size() 请求数组的长度======================public int size() {return size;}   
​
============contain("java05")判断元素是否在集合中==============public boolean contains(Object o) {return indexOf(o) >= 0;}
===============get(1) 获取指定位置的元素========public E get(int index) {rangeCheck(index); //判断指定的位置是否合法 
​return elementData(index);}  
​E elementData(int index) {return (E) elementData[index];} 
​
============toString() 为什么不打印对象的引用地址 [java01, java02, java03, java02]因为重写了Object里面的toString方法。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(' ');}}   通过对ArrayList方法的底层代码分析:底层就是对数组的操作。ArrayList的底层就是基于数组实现的。

4、LinkedList

它是一个链表结构。

4.1 添加

  //添加linkedList.add("java01"); //追加尾部linkedList.addFirst("java02"); //添加到头部linkedList.addLast("java03");//追加到尾部linkedList.addFirst("java04"); //追加到头部linkedList.addLast("java05");//追加到尾部System.out.println(linkedList);

4.2 删除操作

    //删除操作veFirst();//移除头部元素System.out.println(linkedList);
​ve(2);//移除指定位置的元素System.out.println(linkedList);
​veLast();//移除尾部的元素System.out.println(linkedList);

4.3 修改操作

   //修改操作linkedList.set(1,"java11");System.out.println(linkedList);

4.4 查询操作

        //查询操作int size = linkedList.size();//求长度boolean empty = linkedList.isEmpty();//是否为空
​boolean b = ains("java01");//判断元素是否在集合中
​Object o = (1);//根据下标获取指定位置的元素
​Object first = First();//获取第一个元素System.out.println(first);
​Object last = Last();System.out.println(last);

5、set集合(HashSet集合)

 5.1HashSet集合创建

public class Test02 {
    public static void main(String[] args) {
        HashSet  hashSet= new HashSet();

        HashSet  hashSet1 = new HashSet(16);//初始容器的大小

        //loadFactor:--->0.7f 表示负载因子 当空间使用70%时 要求扩容
        HashSet hashSet2 = new HashSet(16,0.7f);
    }
}

5.2添加元素

//t添加操作

hashSet.add("张三");

hashSet.add("李四");

hashSet.add("王五");

hashSet.add("赵六");

hashSet.add("刘七");

//再创建一个新的集合

HashSet set2 = new HashSet();

set2.add("love1");

set2.add("love2");

set2.add("love3");

hashSet.addAll(set2);//把set2中的每个元素添加到hashSet中

System.out.println(hashSet);//元素不能重复,且无序

5.3删除元素

//删除

hashSet.clear();//清空集合容器

5.4查询元素

//查询操作

boolean empty = hashSet.isEmpty();//判断集合是否为空

System.out.println(empty);//true为空,false不为空

boolean a = ains("王五");//判断元素是否在集合中

System.out.println(a);

5.5hashSet遍历

(1)通过foreach进行遍历

for(object a : hashSet){

        System.out.println(a);//输出每个元素

}

(2)通过迭代器进行遍历

Iterator iterator = hashSet.iterator();//获取set中的迭代器对象

//iterator.hasNext() 迭代器判断是否还有下一个未取出的数据  如果有则返回 true  如果没有 则 false 

while (iterator.hasNext()){//判断是否指定能够移动
            Object next = ();//指定移动并获取当前的元素
            System.out.println(next);
        }

5.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<>();
    }

6、TreeSet集合

TreeSet集合和HashSet集合中的方法一模一样,但是实现不一样

TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。

例子: 存储String类型。

TreeSet treeSet=new TreeSet();treeSet.add("java05");treeSet.add("java03");treeSet.add("java04");treeSet.add("java01");treeSet.add("java02");treeSet.add("java04");
​System.out.println(treeSet);

存储一个对象类型:

public class Test04 {public static void main(String[] args) {TreeSet treeSet=new TreeSet();treeSet.add(new Student("张三",17));treeSet.add(new Student("李四",16));treeSet.add(new Student("王五",16));treeSet.add(new Student("赵六",15));
​System.out.println(treeSet);}
}

通过运行我们发现出现如下的错误:

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

解决办法有两个:

第一个: 让你的类实现Comparable接口

public class Test04 {
    public static void main(String[] args) {
        TreeSet treeSet=new TreeSet(); //TreeSet不允许重复元素
        treeSet.add(new Student("张三",17));
        treeSet.add(new Student("李四",16));
        treeSet.add(new Student("王五",16));
        treeSet.add(new Student("赵六",15));

        System.out.println(treeSet);
    }
}
class Student implements Comparable{
     private String name;
     private Integer age;

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

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

    public Student() {
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

        if(this.age>student.age){
            return 1;
        }
        if(this.age<student.age){
            return -1;
        }

        return 0;
    }
}

 第二种: 在创建TreeSet时指定排序的对象。

7、Map 属于键值对模式

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

7.1 如何创建Map对象

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

7.2 添加操作

 //默认初始化大小为16 负载因子为0.75Map map=new HashMap();//添加操作 key: name     value: 高景霞map.put("name","高景霞"); //注意: 要求map得key必须唯一。map.put("age",18);map.put("name","李赛"); //因为key不能重复,所以后者会把前者覆盖
​Map m1=new HashMap();m1.put("k1","v1");m1.put("k2","v2");map.putAll(m1); //把m1中得每个元素 添加到map中
​map.putIfAbsent("age",28) ;//如果指定得key存在,则不放入map中,如果不存在则放入map中
​System.out.println(map);

7.3 删除操作

        //删除操作ve("age2");//根据指定得key移除元素System.out.println(map);map.clear(); //清空map容器System.out.println(map);

7.4 修改操作

     //修改操作place("name","刘德华");//替换元素System.out.println(map);

7.5 查询

public static void main(String[] args) {Map map=new HashMap();map.put("k1","v1");map.put("k4","v4");map.put("k2","v2");map.put("k3","v3");//查询操作boolean f = ainsKey("k5");//判断map是否存在指定得key
​Object v = ("k5"); //根据指定的key获取对应得value值System.out.println(v);
​Set keys = map.keySet();//返回该map中所有得keySystem.out.println(keys);//遍历map.for(Object k:keys){Object value= (k);//System.out.println(k+"================>"+value);}
​}

7.6 HashMap得底层原理

JDK1.7 和 JDK1.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}

 

总结:

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

 

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 keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

本文发布于:2024-02-02 01:55:39,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170681388440663.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:Java学习
标签:框架
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23