1.LinkedList

1.1链式结构

LinkedList也是一个集合,是一个链式结构的集合,删除和增加的效率高

  • 因为提供了大量的首尾操作

  • 常用的方法:
  • void addFirst(E e)—-添加首个元素
  • void addLast(E e)—-添加最后元素
  • E getFirst()————获取首个元素
  • E getLast()————-获取最后元素 ```java package com.igeek_01;

/**

  • @author Lynn
  • @create 2020-12-08-10:04 */

import javax.sound.midi.Soundbank; import java.util.Iterator; import java.util.LinkedList;

public class LinkedListDemo { public static void main(String[] args) { //创建集合对象 LinkedList list=new LinkedList<>(); //向集合中添加数据 list.add(“欧阳锋”); list.add(“王重阳”); list.add(“周伯通”);

  1. //获取元素
  2. String name= list.get(1);
  3. System.out.println(name);
  4. //返回迭代器
  5. Iterator<String> iterator= list.iterator();
  6. //问取删
  7. while (iterator.hasNext()){
  8. String thisName= iterator.next();
  9. System.out.println(thisName);
  10. }
  11. System.out.println("---------------------------------");
  12. //首尾操作
  13. System.out.println(list);
  14. list.addFirst("王嘉尔");
  15. list.addLast("王一博");
  16. System.out.println(list);
  17. System.out.println(list.getFirst());
  18. System.out.println(list.getLast());
  19. //删除
  20. list.remove(3);
  21. System.out.println(list);
  22. }

}

  1. <a name="oxqNN"></a>
  2. # 2.数据结构
  3. <a name="FjPYz"></a>
  4. ### 2.1Stack-----栈
  5. Stack结构的演示
  6. - **栈结构---遵循先进后出的原则**
  7. - <br />
  8. - 对应的方法:
  9. - 1.push:压栈---先进后出
  10. - 2.pop:弹栈--将元素直接弹出--意味着这个元素在栈中没有了
  11. - 3.peek:查询出即将弹出的是哪个元素-检查有没有需要弹出的元素--只看不弹出--
  12. - 意味着元素还在栈中
  13. - <br />
  14. - LinkedList是支持栈结构的
  15. - java中专门提供了一个结构--Stack
  16. ```java
  17. package com.igeek_02;
  18. /**
  19. * @author Lynn
  20. * @create 2020-12-08-10:20
  21. */
  22. import com.sun.prism.shader.Solid_TextureYV12_AlphaTest_Loader;
  23. import java.util.LinkedList;
  24. public class StackDemo {
  25. public static void main(String[] args) {
  26. //创建栈结构
  27. LinkedList<String> stack=new LinkedList<>();
  28. //添加元素
  29. /* stack.add("王嘉尔");
  30. stack.add("王一博");
  31. stack.add("白敬亭");
  32. stack.add("刘诗诗");
  33. stack.add("赵丽颖");
  34. stack.add("谭松韵");*/
  35. //因为支持栈结构,所以有push方法
  36. stack.push("王嘉尔");
  37. stack.push("王一博");
  38. stack.push("白敬亭");
  39. stack.push("刘诗诗");
  40. stack.push("赵丽颖");
  41. stack.push("谭松韵");
  42. //查询结果
  43. System.out.println(stack);
  44. System.out.println("--------------------------");
  45. //获取一个元素,此时由于是栈结构,所以获取的是最后压栈的元素
  46. String name=stack.pop();
  47. System.out.println(name);
  48. System.out.println(stack);
  49. System.out.println("--------------------------");
  50. //peek
  51. String peekname=stack.peek();
  52. System.out.println(peekname);
  53. System.out.println(stack);
  54. }
  55. }

2.2Queue—队列

队列结构演示:

  • 队列结构支持:先进先出的原则

  • LinkedList支持队列结构!!
  • 因为这个LinkedList本身是链式结构,所以添加和删除比较灵活,而栈和队列都是
  • 数据结构中的操作,所以利用LinkedList支持比较方便

  • 对应的方法:
  • offer:加入队列
  • poll:(获取的是最早进入的元素)离开队列—该元素已经不在队列中了
  • peek:查询出即将离开队列的是哪个元素—只看不离开—该元素还在队列中 ```java package com.igeek_02;

/**

  • @author Lynn
  • @create 2020-12-08-10:36 */

import java.util.LinkedList;

public class QueueDemo { public static void main(String[] args) { //利用LinkedList支持队列 LinkedList queue=new LinkedList<>(); //添加元素 queue.offer(“刘德华”); queue.offer(“梅艳芳”); queue.offer(“张国荣”); //先进先出 System.out.println(queue);

  1. System.out.println("----------------------------");
  2. //获取一个元素,此时由于是队列结构,所以获取的是最早进入的元素
  3. System.out.println(queue.poll());
  4. System.out.println(queue);
  5. System.out.println("----------------------------");
  6. //peek
  7. System.out.println(queue.peek());
  8. System.out.println(queue);
  9. }

}

  1. <a name="5d62p"></a>
  2. # 数组结构和链表结构
  3. <a name="aQUKT"></a>
  4. ## 1.1 ArrayList数组实现的原理
  5. 数组实现的特点:查询快,增删慢<br />原因:<br /> 查询快:由于数组的索引支持,那么可以通过索引直接计算出元素的地址值,因此就可以直接通过元素的地址值获取到指定的元素<br />增删慢:由于在添加元素的时候,实际上底层会先创建一个新数组(新数组的长度为原数组的长度+1),那么在添加新元素的时候,先需要对数组中原有的数据进行拷贝,其次在末尾进行添加新的元素<br />因此,这样操作的效率的极低的(删除元素 刚好和添加的操作相反)
  6. <a name="2L8B2"></a>
  7. ## 1.2 LinkedList链表实现的原理
  8. 链表结构:查询慢,增删快<br />查询慢:由于不能直接找到元素的地址,需要上一个元素推导出下一个元素的地址,<br />这种查询速度较慢<br />增删快:在添加的时候,只需要更改元素所记录的地址值即可
  9. <a name="VEAlV"></a>
  10. # 3.HashSet集合
  11. HashSet也是一个集合,**不包含重复的元素和相同的元素,无序的,不提供索引(下标**),
  12. - 所以不能通过下标获取元素,只能通过**迭代器访问---增强for循环**
  13. - <br />
  14. - HashSet怎么做到不重复的?
  15. - 1.首先在元素存放进这个集合之前会通过HashCode()方法算出哈希值(int类型)
  16. - 2.比较当前这个哈希值在集合中是否已经存在,如果存在就不保存
  17. - <br />
  18. - 所以HashSet称之为**无序不可重复**集
  19. ```java
  20. package com.igeek_03;
  21. /**
  22. * @author Lynn
  23. * @create 2020-12-08-11:05
  24. */
  25. import java.util.HashSet;
  26. import java.util.Iterator;
  27. /**
  28. * HashSet也是一个集合,不包含重复的元素和相同的元素,无序的,不提供索引(下标),
  29. * 所以不能通过下标获取元素,只能通过迭代器访问---增强for循环
  30. *
  31. * HashSet怎么做到不重复的?
  32. * 1.首先在元素存放进这个集合之前会通过HashCode()方法算出哈希值(int类型)
  33. * 2.比较当前这个哈希值在集合中是否已经存在,如果存在就不保存
  34. *
  35. * 所以HashSet称之为无序不可重复集
  36. */
  37. public class HashSetDemo {
  38. public static void main(String[] args) {
  39. //创建集合对象
  40. HashSet<String> set=new HashSet<>();
  41. //向集合中添加元素--无序,不可重复
  42. set.add("王嘉尔");
  43. set.add("王嘉尔");
  44. set.add("王一博");
  45. set.add("赵丽颖");
  46. set.add("白敬亭");
  47. set.add("白敬亭");
  48. set.add("谭松韵");
  49. set.add("刘诗诗");
  50. //打印结果
  51. System.out.println(set);
  52. //获取元素--只能使用迭代器
  53. Iterator<String> iterator= set.iterator();
  54. while (iterator.hasNext()){
  55. //推荐向下转型--强类型转换---目的是为了增加代码的健壮性---
  56. //转成最后需要接受的类型
  57. String thisName = (String)iterator.next();
  58. System.out.println(thisName);
  59. }
  60. System.out.println("----------------------");
  61. //增强for循环底层就是一个迭代器
  62. for (String name:set){
  63. System.out.println(name);
  64. }
  65. //普通for循环
  66. for (int i = 0; i < set.size() ; i++) {
  67. //HashSet没有下标,所以不提供get方法,get方法根据下标获取对应元素
  68. // System.out.println(set.get(i));
  69. }
  70. }
  71. }

练习
image.png

  1. package com.igeek_03;
  2. import java.util.HashSet;
  3. import java.util.Iterator;
  4. /**
  5. * @author Lynn
  6. * @create 2020-12-08-11:25
  7. */
  8. /**
  9. * fdasffkdsajfasFJKFDSAJKdfefoeaf
  10. * <p>
  11. * 分析:
  12. * 1.将字符串拆分为一个个单个的字符
  13. * 2.判断字符是否为字母
  14. * 如果是字母,放到一个set集合中
  15. * 3.查看set集合的长度
  16. */
  17. public class HashSetTest {
  18. public static void main(String[] args) {
  19. //准备一个字符串
  20. String s = "fdasffkdsajfasFJKFDSAJKdfefoeaf";
  21. //定义一个不含重复元素的集合
  22. HashSet<Character> set = new HashSet<>();
  23. //拆分字符串
  24. char[] chars = s.toCharArray();
  25. //遍历---无下标的
  26. for (char c : chars) {
  27. //判断字符是否为字母,如果是字母,放到一个set集合中
  28. if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){
  29. set.add(c);
  30. }
  31. }
  32. //查看
  33. System.out.println(set);
  34. System.out.println(set.size());
  35. }
  36. }

4.ArrayList中有一个方法:Contains用来判断是否有重复的元素

boolean Contains(Objects o)—判断集合中是否有指定的元素

  • 为了实现这个功能,我们需要新建一个实体类,是Object的子类,具备了equals方法
  • Contains方法会调用参数的equals方法,依次为集合中的已经存在的对象进行比较

  • 例如:新建一个Person子类继承Object。直接调用equals方法 ```java package com.igeek_04;

/**

  • @author Lynn
  • @create 2020-12-08-14:23 */

/**

  • 实体类 */ public class Person { private String name; private int age;

    public Person() { }

    public Person(String name, int age) {

    1. this.name = name;
    2. this.age = age;

    }

    public String getName() {

    1. return name;

    }

    public void setName(String name) {

    1. this.name = name;

    }

    public int getAge() {

    1. return age;

    }

    public void setAge(int age) {

    1. this.age = age;

    }

    @Override public String toString() {

    1. return "Person{" +
    2. "name='" + name + '\'' +
    3. ", age=" + age +
    4. '}';

    }

    //重写equals方法

    /**

    • 目的是比较两个对象像不像
    • @param obj
    • @return */ @Override public boolean equals(Object obj){ System.out.println(“equals方法被调用了”);

      //this:表示contains方法的参数对象 //obj:集合中原有的对象 //将Object类型的obj强制转换为子类类型(向下转型) Person otherP=(Person)obj;

      //重写比较规则 //比较的是当前的对象的属性:姓名,年龄 if (!this.getName().equals(otherP.getName())){

      1. return false;

      } if (this.getAge()!= otherP.getAge()){

      1. return false;

      } //如果上面两个都不是false,则返回true return true; } } java package com.igeek_04;

/**

  • @author Lynn
  • @create 2020-12-08-14:19 */

import java.util.ArrayList;

public class ArrayListContainsDemo { public static void main(String[] args) { //创建集合 ArrayList list=new ArrayList<>(); //添加元素 list.add(“Jack”); list.add(“Tom”); list.add(“Lucy”);

  1. //判断--Contains方法中大小写敏感
  2. System.out.println(list.contains("jack"));//false
  3. System.out.println("==================================");
  4. //对象比较
  5. ArrayList<Person> list2=new ArrayList<>();
  6. list2.add(new Person("宋远桥",45));
  7. list2.add(new Person("俞莲舟",40));
  8. list2.add(new Person("张翠山",32));
  9. Person p=new Person("殷素素",30);
  10. list2.add(p);
  11. //equals方法默认的比较对象的方式是比较地址值,即==
  12. System.out.println(list2.contains(new Person("宋远桥",45)));
  13. //false--比较的是地址值

// System.out.println(list2.contains(p));//true

  1. }

}

  1. <a name="45QV3"></a>
  2. # 5.HashSet判断元素唯一性
  3. HashSet这个集合中添加元素的方法在执行添加的时候,会判断元素是否已经存在:
  4. - HashSet判断元素唯一性的规则:
  5. - 1.把对象加入到HashSet的时候,会先使用对象的HashCode方法,来生成一个哈希值,
  6. - 判断对象加入的位置
  7. - 2.如果比较的位置,没有其他对象存在,则判断元素不同,可以加入新的对象
  8. - 3.如果比较的位置,有其他对象存在,接着比较HashCode值和equals比较结果
  9. - 返回true则相同,不能存入新的对象,如果是false则不同,添加新的对象
  10. - <br />
  11. - 需求:
  12. - 要求比较两个对象的属性和内容是否相同,而非比较对象的地址值
  13. - 此时我们可以重写Person类中的HashCode方法和equals方法,将Object类中的方法重写
  14. <a name="L0qWW"></a>
  15. ### 重写equals方法
  16. ```java
  17. /*
  18. * 如果没有重写该equals方法,则比较地址值.
  19. * 我们希望比较两个对象时,比较属性内容,所以重写该方法.
  20. */
  21. /**
  22. * @Title: equals
  23. * @Description: Person对象比较是否相等的方法
  24. * @param obj
  25. * @return
  26. * @see java.lang.Object#equals(java.lang.Object)
  27. */
  28. @Override
  29. public boolean equals(Object obj) {
  30. System.out.println("equals方法被调用了");
  31. //this:contains方法的参数对象
  32. //obj:集合当中原有元素
  33. //将Object类型的obj强转为子类类型
  34. Person otherP = (Person)obj;
  35. //比较姓名
  36. if(!this.name.equals(otherP.name)) {
  37. return false;
  38. }
  39. //比较年龄
  40. if(this.age != otherP.age){
  41. return false;
  42. }
  43. //如果所有属性值均相同,就返回true
  44. return true;
  45. }

重写HashCode方法

  1. //没有重写hashCode方法时,hashCode方法继承父类方法,返回的是地址值
  2. //重写hashCode方法,通过属性值返回一个整数数字
  3. //即对象的hashCode值,就是各个属性的hashCode值之和
  4. //引用数据类型属性,调用hashCode方法回去
  5. //基本数值类型属性,直接就是数值本身
  6. /**
  7. * @Title: hashCode
  8. * @Description: Person对象的hashCode值算法方法
  9. * @return
  10. * @see java.lang.Object#hashCode()
  11. */
  12. @Override
  13. public int hashCode() {
  14. //张三 18 >> 56*系数 + 18 = 74
  15. //李四 56 >> 18*系数 + 56 = 74
  16. //理想上,不同属性值应该返回不同的hashCode值,可以在每次结果后乘以一个固定系数,避免该情况发生
  17. //定义变量,记录要返回的hashCode值
  18. int thisHashCode = 0;
  19. //获取name属性的hashCode值
  20. thisHashCode += name.hashCode()*17;
  21. //获取age数只给你的hashCode值
  22. thisHashCode += age;
  23. return thisHashCode;
  24. }
  1. package com.igeek_05;
  2. /**
  3. * @author Lynn
  4. * @create 2020-12-08-14:23
  5. */
  6. /**
  7. * 实体类
  8. */
  9. public class Person1 {
  10. private String name;
  11. private int age;
  12. public Person1() {
  13. }
  14. public Person1(String name, int age) {
  15. this.name = name;
  16. this.age = age;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public int getAge() {
  25. return age;
  26. }
  27. public void setAge(int age) {
  28. this.age = age;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Person{" +
  33. "name='" + name + '\'' +
  34. ", age=" + age +
  35. '}';
  36. }
  37. //重写equals方法
  38. /**
  39. * 目的是比较两个对象像不像
  40. * @param obj
  41. * @return
  42. */
  43. @Override
  44. public boolean equals(Object obj){
  45. System.out.println("equals方法被调用了");
  46. //this:表示contains方法的参数对象
  47. //obj:集合中原有的对象
  48. //将Object类型的obj强制转换为子类类型(向下转型)
  49. Person1 otherP=(Person1)obj;
  50. //重写比较规则
  51. //比较的是当前的对象的属性:姓名,年龄
  52. if (!this.getName().equals(otherP.getName())){
  53. return false;
  54. }
  55. if (this.getAge()!= otherP.getAge()){
  56. return false;
  57. }
  58. //如果上面两个都不是false,则返回true
  59. return true;
  60. }
  61. //重写HashCode方法
  62. public int hashCode(){
  63. System.out.println("hashCode方法被调用了");
  64. //定义一个变量
  65. int thisHashCode=0;
  66. //张三,18 56*系数+18=74
  67. //李四,56 18*系数+56=74
  68. //获取name属性的HashCode值
  69. thisHashCode+=this.name.hashCode()*17;
  70. //获取age属性的HashCode值,就是age本身
  71. thisHashCode+=this.age;
  72. return thisHashCode;
  73. }
  74. }
  1. package com.igeek_05;
  2. /**
  3. * @author Lynn
  4. * @create 2020-12-08-15:07
  5. */
  6. import java.util.HashSet;
  7. public class HashSetAddDemo1 {
  8. public static void main(String[] args) {
  9. HashSet<Person1> set=new HashSet<>();
  10. Person1 p=new Person1("张三丰",120);
  11. Person1 p2=new Person1("郭襄",100);
  12. Person1 p3=new Person1("杨过",110);
  13. //添加到集合中
  14. set.add(p);
  15. set.add(p2);
  16. set.add(p3);
  17. // System.out.println(set);
  18. //调用equals方法
  19. //再次调用add方法添加新元素--不可以添加原有的元素
  20. set.add(new Person1("郭襄",100));
  21. System.out.println(set);
  22. }
  23. }

Java单列集合框架之总结&体系图

单列集合体系图

image.png
Collection:所有单列集合的直接或间接接口,其指定了所有集合应该具备的基本功能。
List:元素可重复,有序,带索引
Set:元素不能重复,没有索引
ArrayList(重要) :底层是数组结构。ArrayList的出现替代了Vector,增删慢,查找快
LinkedList(重要):底层是链表结构。同时对元素的增删操作效率很高
HashSet(重要) :底层是哈希表结构。在不重复的基础上无序
LinkedHashSet:底层是哈希表结构结合链表结构。在不重复的基础上可预测迭代顺序