Java集合(2)——基础介绍(2)——与集合有关的数据结构、List接口、Set接口

目录

1.与集合有关的几种数据结构

(1)栈

(2)队列

(3)数组

(4)链表

(5)红黑树

2.List接口

3.List集合的实现类

3.1 ArrayList集合

(1)常用构造方法

(2)常用方法

(3)ArrayList存储基本数据类型

(4)ArrayList的部分源码

3.2 LinkedList集合

3.3 Vector集合

4.Set接口及其实现类

4.1 HashSet

(1)HashSet实现类的特点

(2)哈希表

1)哈希值

2)哈希表

(3)Set集合中元素不重复的原理

4.2 LinkedSet


1.与集合有关的几种数据结构

(1)栈

(2)队列

(3)数组

(4)链表

(5)红黑树

2.List接口

List接口特点:

  • 1.它是一个元素存取有序的集合。(有序的意思是说存储和取出元素的顺序是一致的)例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。

  • 2.它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。

  • 3.集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

List接口中常用带索引的方法:

注意:操作索引的时候一定要防止索引越界异常

代码演示:

package com.boboyu;

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

public class Demo01 {
    public static void main(String[] args) {
        //创建一个List集合对象,多态
        List<String> list = new ArrayList<>();
        //1.使用add方法往list集合中添加元素
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("a");

        //public void add(int index, E element)`: 将指定的元素,添加到该集合中的指定位置上。
        //2.在c和d之间添加“boboyu”
        list.add(3,"boboyu");

        System.out.println(list);  //重写了toString方法

        //public E remove(int index)`: 移除列表中指定位置的元素, 返回的是被移除的元素。
        //3.移除指定元素
        String removeEle = list.remove(2);
        System.out.println("被移除的元素是:"+removeEle);
        System.out.println(list);

        //public E set(int index, E element)`:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
        //4.把最后一个a替换为A
        String setEle = list.set(3,"A");
        System.out.println("被替换的元素为:"+setEle);
        System.out.println(list);

        //5.List的三种遍历方式
        //第一种:使用普通循环来遍历List
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("------------------");

        //第二种:使用迭代器遍历List
        Iterator<String> it = list.iterator();
        while(it.hasNext())
        {
            String s=it.next();     //这里一定要使用临时对象来获取next方法的返回结果,
                                    //不能在循环中多次调用next方法,因为每调用一次指针都会后移一位
            System.out.println(s);
        }

        System.out.println("------------------");

        //第三种:使用增强for循环遍历List
        for (String s : list) {
            System.out.println(s);
        }
    }
}

3.List集合的实现类

3.1 ArrayList集合

与数组的最大区别:数组的长度不可以发生变化,而ArrayList集合的长度是可以变化的

(1)常用构造方法

代码示例:

package com.boboyu;

import java.util.ArrayList;

public class Demo01 {
    public static void main(String[] args) {
        //创建一个ArrayList集合对象list
        //备注:从JDK1.7开始,右侧的尖括号内可以不写内容,但<>本身还是要写的
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list); //对于ArrayList来说,直接打印的不是地址值,而是内容
                                  //如果内容是空,得到的是空的中括号:[]

    }
}

(2)常用方法

同上述List接口中的add、get、remove、set方法

三种遍历方法也参考上述List接口

(3)ArrayList存储基本数据类型

如果希望往ArrayList中存储基本数据类型,必须使用基本数据类型对应的包装类

基本类型

包装类(引用类型,位于java.lang包下)

 
byteByte 
shortShort 

int

Integer特殊
longLong 
floatFloat 
doubleDouble 
charCharacter特殊
booleanBoolean 

 

 

 

 

 

 

 

 

 

package com.boboyu;

import java.util.ArrayList;


public class Demo01 {
    public static void main(String[] args) {
        //错误写法,泛型只能使用引用类型,不能使用基本类型
        //ArrayList<int> list01 = new ArrayList<>();

        ArrayList<Integer> list02 = new ArrayList<>();
        list02.add(100);
        list02.add(200);
        System.out.println(list02);

        int num=list02.get(1);
        System.out.println("索引1处的元素是:"+num);
        //注意:从java1.5开始,支持自动装箱、自动拆箱
        //    自动装箱:基本类型---->包装类型
        //    自动拆箱:包装类型---->基本类型
    }
}

(4)ArrayList的部分源码

不是同步的就意味着多线程,效率高

  • 1.ArrayList底层就是数组

  • 2.ArrayList的add方法底层是先判断,元素个数+1后是否大于底层数组的长度,如果大于,进行扩容,建立一个新的数组,并将原来数组中的元素复制到新的数组的对应位置

注意:开发时不能随意地使用ArrayList完成任何需求

3.2 LinkedList集合

LinkedList的特点:

  • 1.底层是一个双向链表:查询慢,增删快
  • 2.里边包含了大量的操作首尾元素的方法
  • 3.即为多线程
  • 注意:使用LinkedList集合中特有的方法时,不能使用多态

LinkedList操作首尾元素的方法:

1)添加的方法

package com.boboyu;

import java.util.LinkedList;

public class Demo01 {
    public static void main(String[] args) {
        show01();
    }
    //添加元素演示
    private static void show01()
    {
        //创建LinkedList集合对象
        LinkedList<String> linked = new LinkedList<>();
        //使用add方法往集合添加元素
        linked.add("a");
        linked.add("b");
        linked.add("c");
        System.out.println(linked);

        //使用addFirst将指定元素添加到链表的头部
        linked.addFirst("boboyu0");

        System.out.println(linked);
        //使用push将指定元素添加到链表的头部
        linked.push("boboyu1");

        System.out.println(linked);

        //使用addLast将指定元素添加到链表的尾部,此方法等效于add
        linked.addLast("boboyu2");
        System.out.println(linked);
    }
    
}

2)获取元素的方法

package com.boboyu;

import java.util.LinkedList;

public class Demo01 {
    public static void main(String[] args) {
        show02();
    }
    //添加元素演示
    private static void show02()
    {
        //创建LinkedList集合对象
        LinkedList<String> linked = new LinkedList<>();
        //使用add方法往集合添加元素
        linked.add("a");
        linked.add("b");
        linked.add("c");

        String first1=linked.getFirst();
        System.out.println("linked的第一个元素为:"+first1);
        String last1=linked.getLast();
        System.out.println("linked的最后一个元素为:"+last1);

        linked.clear();//清空集合中的元素,在获取集合中的元素时会抛出NoSuchElementException

        if(!linked.isEmpty())
        {
            String first2=linked.getFirst();
            System.out.println("linked的第一个元素为:"+first2);
            String last2=linked.getLast();
            System.out.println("linked的最后一个元素为:"+last2);
        }
    }

}

3)移除方法

package com.boboyu;

import java.util.LinkedList;

public class Demo01 {
    public static void main(String[] args) {
        show03();
    }
    //移除元素演示
    private static void show03()
    {
        //创建LinkedList集合对象
        LinkedList<String> linked = new LinkedList<>();
        //使用add方法往集合添加元素
        linked.add("a");
        linked.add("b");
        linked.add("c");
        linked.add("d");

        System.out.println(linked);

        System.out.println(linked.removeFirst());

        System.out.println(linked.removeLast());
        System.out.println(linked);

        System.out.println(linked.pop());   //pop相当于removeFirst
        System.out.println(linked);
    }

}

3.3 Vector集合

与ArrayList相同的是底层都是数组,不同的是Vector是同步的,同步的就是单线程的,速度慢,后面被ArrayList取代了

4.Set接口及其实现类

java.util.Set接口和java.util.List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了

特点:

  • 1.不包含重复元素
  • 2.这个接口没有索引,没有带索引的方法,也不能使用普通的for循环来遍历

4.1 HashSet

(1)HashSet实现类的特点

  • 1.不包含重复元素
  • 2.这个接口没有索引,没有带索引的方法,也不能使用普通的for循环来遍历
  • 3.是一个无序的集合,存储元素和取出元素的顺序有可能不一致
  • 4.底层是一个哈希表结构,查询非常快
package com.boboyu;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Demo01 {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();

        set.add(1);
        set.add(3);
        set.add(2);
        set.add(1);

        //1.使用迭代器遍历set集合
        Iterator<Integer> it = set.iterator();
        while(it.hasNext())
        {
            Integer n = it.next();
            System.out.println(n);
        }

        //2.使用增强for循环遍历set集合
        System.out.println("-----------------");
        for(Integer i : set)
        {
            System.out.println(i);
        }
    }

}

(2)哈希表

1)哈希值

哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值),是一个逻辑地址,是一个模拟出来的地址,不是数据实际存储的物理地址

在Object类中有一个方法,可以获取对象的哈希码值

以下是hashCode()的源码

native表明该方法调用的是本地操作系统的方法

代码示例:

package com.boboyu;

public class Demo01 {
    public static void main(String[] args) {
        Person p1 = new Person();
        int h1 = p1.hashCode();
        System.out.println(h1);

        Person p2 = new Person();
        int h2 = p2.hashCode();
        System.out.println(h2);

        /*
        toString方法的源码
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
         */
        System.out.println(p1);
        System.out.println(p2);
    }

}

class Person {

}

String类重写了Object类的hashCode方法

package com.boboyu;

public class Demo01 {
    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());

        System.out.println("重地".hashCode());
        System.out.println("通话".hashCode());
    }

}

2)哈希表

总而言之,JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

(3)Set集合中元素不重复的原理

(4)HashSet存储自定义类型的元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一 

示例代码:

要求:同名同年龄的人,视为同一个人,只存储一次

不重写hashCode和equals方法:

Person.java

package com.boboyu;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", 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;
    }
}

Demo01.java

package com.boboyu;

import java.util.HashSet;

public class Demo01 {
    public static void main(String[] args) {
        //创建一个HashSet集合,让它存储Person
        HashSet<Person> set = new HashSet<>();
        Person p1 = new Person("小明",18);
        Person p2 = new Person("小明",18);
        Person p3 = new Person("小明",19);
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());

        System.out.println(p1==p2);
        System.out.println(p1.equals(p2));
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);
    }
}

可以发现在没有重写hashCode和equals方法前,相同姓名和相同年龄的对象是不同的对象

重写hashCode和equals方法:

Person.java

package com.boboyu;

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, 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;
    }
}

Demo01.java

package com.boboyu;

import java.util.HashSet;

public class Demo01 {
    public static void main(String[] args) {
        //创建一个HashSet集合,让它存储Person
        HashSet<Person> set = new HashSet<>();
        Person p1 = new Person("小明",18);
        Person p2 = new Person("小明",18);
        Person p3 = new Person("小明",19);
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());

        System.out.println(p1==p2);
        System.out.println(p1.equals(p2));
        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);
    }
}

4.2 LinkedSet

LinkedSet继承了HashSet

特点:

  • 底层是一个哈希表(数组+链表/红黑树)+链表,多了一条链表(记录元素的存储顺序),保证元素有序

示例代码:

package com.boboyu;

import java.util.HashSet;
import java.util.LinkedHashSet;

public class Demo01 {
    public static void main(String[] args) {

        HashSet<String> set = new HashSet<>();
        set.add("www");
        set.add("abc");
        set.add("abc");
        set.add("com");
        System.out.println(set); //无序,不允许元素重复

        LinkedHashSet<String> linked = new LinkedHashSet<>();
        linked.add("www");
        linked.add("abc");
        linked.add("abc");
        linked.add("com");
        System.out.println(linked); //有序,不允许元素重复
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值