zoukankan      html  css  js  c++  java
  • Collection的另外一个子类LinkedList&Set集合

    Set集合和List集合的区别不大,只是Set不可重复,List可重复
    Set无序,List有序
    集合只要能实现的功能,Set和List都能实现没只不过是选择哪个做最优解的问题

    计算机的内存中,有的是连续的内存空间,比如数组,就是连续的内存空间。除了这些连续的内存空间以外,剩下的内存空间都是以链表的形式存在。

    链表又分为单向链表和双向链表:

    单向链表:一个单向链表分为一个数据域和一个指针域,指针域里存放的是下一个单向链表的地址

    双向链表:一个双向链表分为一个数据域,两个指针域,第一个指针存放的是前一个双向链表的地址,第二个指针域存放的是下一个双向链表的地址

    Collection集合的两个子类:ArrayList和LinkedList:

    ArrayList的底层是数组,LinkedList的底层是一个链表

    那么来区分呢一下数组和集合在进行数据的CURD(增删改查)的时候的优缺点

    数组由于是连续的内存空间,有序列号(下标),所以数组在进行数据的查询时速度快于集合,但是正是由于数组的连续空间组织,使得数组再进行数据的增删时慢于集合,集合只需要将链表断开,重连即可

    而数组要一位一位的换位置,所以数组的增删要慢于集合。

    这也正是底层的结构决定了上层的应用。

    队列:就和队伍一样,先进先出。

    栈:先进后出,虚拟机里的栈是底端封口的。

     ArrayList<String>  list=new ArrayList<>();  泛型:前边的尖括号里写了泛型的类型,后边的尖括号里就可以不用写了,会自动推断出泛型的类型的(在java1.7版本以后出现的)

    关于上一篇的抽象类和接口的向上转型问题,我的想法得到了肯定。

    Syso(" ")

    Scanner sc =new Scanner(System.in);

    只要将sc这个对象创建出来,在作用域里,就可以进行多次的调用。

    Iterator it =list.iterator();

    it.hasNext();  哈希Next方法,判断这个对象的哈希地址是否为空。

    在编译器进行编译的时候,会将整个包都进行编译, 所以这个包下只要有同名的类,就会报错。

    泛型的四种常用类型  E:element   T : type   K:key   V:value

    不能有静态泛型类,因为虚拟机一运行,就将静态的东西加载到内存中,而泛型是非静态的,泛型要等到创建对象之后才能加载到内存中,所以静态类加载时泛型不具体,不能有静态泛型类。

    泛型的好处:只需要写一个方法,任何类型的数据都可以使用,必方法的重载还要方法,代码的重用率高。

    泛型的通配符  ?

    java.lang包下的所有东西,使用的时候都不需要导包。

    静态导入:将java.lang包用static修饰,然后导入  以后在使用System.out.println()  时,写为out.println() 即可。

    可变参数: fun();

      public void fun(int... a) fun(){

    }  想给fun方法传递几个参数都可以,当参数列表有很多参数时,可变参数必须放在最后一个,这样才好区分哪些为别的参数,那些为可变参数

    Set:Collection集合的另一个子类:

    Set和List的区别:

    List是有序,可重复的

    Set是无序,不可重复的

    对于Set的不可重复:相同类型的对象,无论你存储多少个,Set集合只保留一个(自定义对象:针对重写hashCode方法和equals方法,若不重写

    hashCode方法和equals方法,Set只能通过地址来判断是否相同,做不到不重复)

    加载因子:某集合的容量为16,若它的加载因子为1,则只有当16个元素都存储满了,才会扩容,当加载因子为0.75时,集合容量为100,存储75个

    对象,就会扩容

    哈希冲突:哈希值计算出的索引位置重复,导致该索引位置已经存储了元素,但是还有元素需要存储在这个索引位置,这叫哈希冲突,也叫哈希碰撞

    hasCode方法重写的原理:看元素的哈希值是否相同

    hashCode方法未重写前:根据地址返回一个哈希值

    Set的存储原理:

    首先调用元素对象的hashCode方法,来判断该位置有无元素,若无元素,则直接插入

    若有元素,则调用元素对象的equals方法,判断元素对象的值是否相同,若相同,则不插入,若不相同,则链式插入,当达到八个元素时,

    使用红黑树进行插入。

    LinkedList代码演示

     1 public class LinkedList 类 {
     2 public static void main(String[] args) {
     3 // 创建对象
     4 LinkedList<String> list=new LinkedList<>();
     5 // 添加方法
     6 list.add("1");
     7 list.add("2");
     8 list.add("3");
     9 list.add(1, "4");
    10 System.out.println(list);
    11 }
    12 }

    1. day05 课堂笔记
    1.1. List 集合
    1.1.1. LinkedList
    底层 : 双向链表
    特点: 增删操作比 ArrayList 速度快,但是查询慢。可以当做栈或者队列使用。
    补充内容 :
    ① 队列: 特点 : 先进先出。
    ② 栈:特点: 先进后出 。
    代码演示:

     1 public class LinkedList 类 {
     2 public static void main(String[] args) {
     3 // 创建对象
     4 LinkedList<String> list=new LinkedList<>();
     5 // 添加方法
     6 list.add("1");
     7 list.add("2");
     8 list.add("3");
     9 list.add(1, "4");
    10 System.out.println(list);
    11 }
    12 }


    1.1.2. Vector
    ( 了解并知道 )
    1.Vector : 它是同步的,用法同 Arraylist, 底层也是可变数组。但是效率低
    2. 遍历方式 : Enumeration
    ① hasMoreElements 相当于 hashNext
    ② nextElement 相当于 next
    ***3. LinkedList 与 Arraylist 、 Vector 分别有什么特点?
    相同点 :有序 ,可重复
    不同点:
    ArrayList 底层: 可变数组,查询速度快,增删慢。线程不安全
    LinkedList 底层:双向链表,增删快,查询速度慢。线程不安全
    Vector 底层: 可变数组,线程安全的,效率低。用法同 ArrayList
    代码演示:

     1 public class Vector 类 {
     2 public static void main(String[] args) {
     3 // 创建对象与添加元素
     4 Vector<String> v=new Vector<>();
     5 v.add("1");
     6 v.add("2");
     7 v.add("3");
     8 // 遍历
     9 Enumeration<String> el = v.elements();
    10 while(el.hasMoreElements()) {
    11 String ne = el.nextElement();
    12 System.out.println(ne);
    13 }
    14 }
    15 }


    2. 泛型
    了解
    1. 泛型 : 参数化类型 。 -- 》数据类型可变 --- 》 存储数据类型的值的变量。
    ① 参数?
    2. 泛型的分类:
    ① 泛型类:在类的声明上加泛型
    ② 泛型接口 : 在接口上加泛型 , 用法同类。
    ③ 泛型方法。
    1> 广义上,在方法上使用泛型。 ( 不算真正的泛型方法。 )
    2> 真正的泛型方法 格式 :
    权限修饰符 修饰符 < 泛型的名称 > 返回值前 方法名称 ( 参数列表 )
    3. 注意:
    ① 泛型在创建对象时,必须要具体指定。如果没带泛型,表示 Object 类型。
    ② 泛型的名称实质就是标识符,一般用字母表示。其实,泛型的名称没有区别,但是 E T K V 名称的
    泛型。
    这四种只是名称含义上的区别,用法没区别 : E : element 元素 T : type 类型 K : key
    键 V: value 值
    ③ 静态方法不能使用类、接口上的泛型,如果需要加泛型,使用泛型方法。
    代码演示:

     1 public class 泛型 {
     2 public static void main(String[] args) {
     3 Collection<String> c=new ArrayList<String>();// String E="String"
     4 Collection<Integer> c1=new ArrayList<>();// E="Integer"
     5 // 泛型类 求两个数加法
     6 M<Integer> m=new M();
     7 m.add(10, 16);
     8 M<Double> m1=new M();
     9 m1.add(10.5, 20.3);
    10 // 调用 add 方法 执行 Byte 类型的数据的加法。
    11 M m2=new M();
    12 // 如果需要多个泛型,可以通过 , 隔开。
    13 /*M1<Integer,Double> m3=new M1();
    14 m3.add(10, 12.5);*/
    15 // 泛型方法
    16 M1<Integer> m4=new M1();
    17 m4.add(10, 15.1);
    18 }
    19 }
    20 // 泛型类
    21 class M<E>{
    22 // 求两个数的加法 - 》求两个整数 / 浮点型 / 一个整数和一个浮点型 的加法
    23 // 要求只要是数据类型相同的两个数都可以。
    24 public void add(E a,E b) {
    25 }
    26 /*public void add(double a,double b) {
    27 }*/
    28 }
    29 // 泛型类进阶 :
    30 class /*M1<E,T>*/M1<E>{
    31 // 一个整数和一个浮点型 的加法 参数可能不一样。
    32 public <T>void add(E a, T b) {
    33 }
    34 public static <M>void fun(M a) {
    35 }
    36 }
    37 // 泛型接口
    38 interface T<T>{
    39 }


    2.1. 泛型的细节问题
    1. 泛型的好处:
    ① 提高代码的重用性。
    ② 进行类型转换
    ③ 安全性。提高程序的健壮性。
    2. 集合中泛型的特点:
    ① 在 1.7jdk 之后 ,菱形技术
    ② 可擦除技术。
    在 class 文件中不存在,在源文件中存在。
    3. 泛型的可传递性:
    如果子类要指定泛型,需要具体指定父类的泛型
    4. 泛型的通配符: ? 当不知道传递的数据类型是什么时,可以使用通配符表示。
    ① 通配符的上限限定:
    格式 : ? extends T 表示 T 和它的子类可以使用
    ② 通配符的下限限定
    格式 : ? super T 表示 T 和它的父类可以使用。
    代码演示:
    public class 泛型的细节问题 {
    public static void main(String[] args) {
    // 在 1.6jdk 之前,集合中泛型必须是补全。但是 1.7 之后,对象上的泛型可以根据引用上的数据类型进行推断,省略
    不写。
    ArrayList<String> list=new ArrayList<String>();
    // 在 1.7jdk 之后,菱形技术就是根据类型推断,省略对象上的数据类型
    ArrayList<String> list1=new ArrayList<>();
    fun2(new ArrayList<String>());
    fun2(new ArrayList<Integer>());
    }
    public static void fun2(ArrayList<?> list) {//Integer Double Person
    /*// 执行集合的添加方法
    list.add("1");
    list.add("2");
    // 添加一个字符串 concat
    String s = list.get(0);*/
    }
    }
    3. JDK1.5 新特性
    1.5jdk :
    ① 静态导入:在导包的时候 加入了 static 关键字
    ② 可变参数:实质是一个参数数组。一般作为最后的参数使用
    ③ 增强 for 循环
    代码演示:
    public class JDK1_5 新特性 {
    public static void main(String[] args) {
    /*out.println("aa");
    floor(15.1);*/
    fun(10,15);
    fun(10,15,17);
    }
    // 求两个整数的和
    public static void fun(int... a) {
    //
    int sum=0;
    for (int i : a) {
    sum+=i;
    }
    System.out.println(sum);
    }
    }
    4. Set 集合
    1. 对于自定义元素的 Set 集合的存储,不能保证集合没有重复元素的。如果需要去重复元素,就是根据 Set 集
    合存储数据的原理进行去重操作。
    2. 存储元素的原理:
    ① hashCode 与 equals 方法。
    ***② 对于自定义类来说, HashSet 集合去重,需要重写 hashCode 与 equals 方法。
    ***③ 存储原理:
    1 》 HashSet 集合存储元素时,首先调用元素对象的 hashCode 方法,根据哈希码值计算出该元素在
    哈希表中的索引位置。
    2 》
    a) 如果该位置,没有元素存在,直接存储在该位置。
    b) 如果该位置有元素存在,这种现象称为哈希冲突 / 哈希碰撞。该现象发生后,会调用 equals 方
    法与该位置的元素进行比较。
    i) 如果两个元素相同,不插入。
    ii) 如果两个元素不相同,插入,在 1.8jdk 之后,如果长度不超过 8 个,采用链表形式 ,如果
    长度超过 8 个,采用红黑树。
    代码演示:

     1 public class HashSet 集合存储自定义对象 {
     2 public static void main(String[] args) {
     3 HashSet<Teacher> set=new HashSet<>();
     4 set.add(new Teacher(" 张三 ", 19));
     5 set.add(new Teacher(" 李四 ", 19));
     6 set.add(new Teacher(" 王五 ", 19));
     7 set.add(new Teacher(" 王五 ", 19));
     8 System.out.println(set);
     9 }
    10 }
    11 class Teacher{
    12 String name;
    13 int age;
    14 int age;
    15 public Teacher() {
    16 super();
    17 // TODO Auto-generated constructor stub
    18 }
    19 public Teacher(String name, int age) {
    20 super();
    21 this.name = name;
    22 this.age = age;
    23 }
    24 @Override
    25 public String toString() {
    26 return "Teacher [name=" + name + ", age=" + age + "]";
    27 }
    28 @Override
    29 public int hashCode() {
    30 final int prime = 31;
    31 int result = 1;
    32 result = prime * result + age;
    33 result = prime * result + ((name == null) ? 0 : name.hashCode());
    34 return result;
    35 }
    36 @Override
    37 public boolean equals(Object obj) {
    38 if (this == obj)
    39 return true;
    40 if (obj == null)
    41 return false;
    42 if (getClass() != obj.getClass())
    43 return false;
    44 Teacher other = (Teacher) obj;
    45 if (age != other.age)
    46 return false;
    47 if (name == null) {
    48 if (other.name != null)
    49 return false;
    50 } else if (!name.equals(other.name))
    51 return false;
    52 return true;
    53 }
    54 }
    55 4.1. HashSet 集合遍历方式
    56 1.HashSet 集合遍历方式:
    57 ** ① 增强 for
    58 ** ② 迭代器 Iterator
    59 ( 了解 )③ 转数组 :toArray(T[] a)
    60 代码演示:
    61 public class HashSet 集合的遍历 {
    62 public static void main(String[] args) {
    63 HashSet<String> set=new HashSet<>();
    64 set.add("1");
    65 set.add("2");
    66 set.add("3");
    67 set.add("4");
    68 //① 增强 for
    69 /*for(String s:set) {
    70 System.out.println(s);
    71 }*/
    72 //② 迭代器 Iterator
    73 /*Iterator<String> it = set.iterator();
    74 while(it.hasNext()) {
    75 System.out.println(it.next());
    76 }*/
    77 // ③ 转数组
    78 String[] a=new String[set.size()];
    79 String[] array = set.toArray(a);
    80 // 数组的遍历
    81 for (int i = 0; i < array.length; i++) {
    82 System.out.println(array[i]);
    83 }
    84 }
    85 }
  • 相关阅读:
    how to read openstack code: loading process
    how to read openstack code: request extension
    how to read openstack code: action extension
    b站刷赞 B站刷赞工具 bilibili评论刷赞 b站点赞
    利用邓西百度网盘消息群发工具对百度网盘的群组、好友进行管理,批量分享文件
    如何利用邓西百度网盘批量转存检测工具批量检测百度网盘失效分享链接
    如何使用邓西百度网盘批量重命名工具对百度网盘中的文件进行批量改名、删除等
    如何利用邓西百度网盘消息群发工具批量删除百度网盘单向好友
    如何利用工具自动通过百度网盘好友请求并发送消息或文件
    邓西百度网盘批量保存检测工具高级用法之分享链接以指定名称保存
  • 原文地址:https://www.cnblogs.com/ywzbky/p/10672874.html
Copyright © 2011-2022 走看看