欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

集合

程序员文章站 2022-03-21 17:05:02
...

1.数组和ArrayList的区别
(1)数组 : 长度固定,有默认值,可以存放基本数据类型,也可以存放引用数据类型

              int[]     -> 0
             double[] -> 0.0
             String[] -> null
             Person[] -> null

(2)ArrayList : 长度变化,没有默认值,引用数据类型

            ArrayList<Integer> list = new ArrayList<>();
            list.add(1);

            ArrayList<数据类型> persons = new ArrayList<数据类型>();
            ArrayList<Person> persons = new ArrayList<>();

2.集合的继承体系

集合

3.Collection集合的常用功能
(1).boolean add(E e): 添加元素
(2).boolean remove(Object o): 删除元素
(3).int size(): 查看集合大小
(4).void clear(): 清空集合

4.迭代器使用
(1)为什么要迭代器
因为Set接口这边的体系没有索引的.没有索引就不能使用for循环+get(索引)的方式来获取元素,所以集合搞了一种通用的获取元素方式

(2)迭代器 : 集合通用的获取元素的方式(Iterator)

(3)迭代器的常用方法
hasNext(): 如果有下一个元素返回true
next(): 取出下一个元素

5.迭代器迭代原理
集合

6.增强for循环遍历数组
(1)增强for遍历数组底层使用普通for
集合

(2)增强for循环遍历集合底层是迭代器

public class Demo07 {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("唐伯虎");
        list.add("祝枝山");
        list.add("文征明");
        list.add("周文宾");

        // 增强for
        for (String str : list) {
            System.out.println(str);
        }

        // 增强for循环遍历集合底层是迭代器
        String str;
        //  走一次
        for (Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(str)) {
            str = (String)iterator.next();
        } // for循环中如果只有一句代码可以省略{}, 不建议

        // 迭代器
//      Iterator<String> itr = list.iterator();
//      while (itr.hasNext()) {
//          System.out.println(itr.next());
//      }

        // 普通for
//      for (int i = 0; i < list.size(); i++) {
//          System.out.println(list.get(i));
//      }
    }
}

7.LinkedList的基本使用
(1).add添加
(2).add添加到指定的索引
(3).修改指定索引的元素
(4).遍历
(5).删除指定索引
(6).清空LinkedList

8.数组结构

int[] arr = new int[] {11, 22, 33, 44};

数组结构特点: 数组保存在堆中,是连续存放的,查询速度快,增加和删除慢

集合

9.链表结构
链表结构特点: 在堆中不连续存储,查询速度慢,添加和删除速度快
集合

10.ArrayList和LinkedList底层实现
(1)ArrayList底层使用
ArrayList底层使用的是数组,查询快,增删慢 (QQ好友)
如果不确定就用ArrayList

(2)LinkedList底层使用
LinkedList底层使用的是链表: 查询慢,增删快(打麻将)

11.因此,LinkedList特有方法
(1).void addFirst(E e): 添加到最前面
(2).void addLast(E e): 添加到最后面
(3).E getFirst(): 获取第一个元素
(4).E getLast(): 获取最后一个元素
(5).E removeFirst(): 删除第一个元素
(6).E removeLast(): 删除最后一个元素

public class Demo06 {

    public static void main(String[] args) {
        // 和头尾相关的方法
        LinkedList<String> linked = new LinkedList<>();

        linked.add("马云");
        linked.add("马化腾");
        linked.add("马景涛");

        // 1.void addFirst(E e): 添加到最前面
        linked.addFirst("马超");

        // 2.void addLast(E e): 添加到最后面
        linked.addLast("马赛克");

        // 3.E getFirst(): 获取第一个元素
        System.out.println(linked.getFirst());

        // 4.E getLast(): 获取最后一个元素
        System.out.println(linked.getLast());

        // 5.E removeFirst(): 删除第一个元素
        linked.removeFirst();

        // 6.E removeLast(): 删除最后一个元素
        linked.removeLast();

        System.out.println(linked);
    }
}

12.Set接口特点
(1)没有索引,没有顺序,元素不可重复
(2)类HashSet和LinkedHashSet都是接口Set的实现,两者都不能保存重复的数据。主要区别是HashSet不保证集合中元素的顺序,即不能保证迭代的顺序与插入的顺序一致

13.HashSet
(1)对于HashSet而言,它是基于HashMap来实现的,底层采用HashMap来保存元素
(2)
集合
(3) isEmpty(),判断HashSet()集合是否为空,为空返回 true,否则返回false。
(4) contains(),判断某个元素是否存在于HashSet()中,存在返回true,否则返回false
(5)当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相 等
注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

14.LinkedHashSet
(1)没有索引,有顺序,元素不可重复
(2)LinkedHashSet是具有可预知迭代顺序的Set接口的哈希表和链接列表实现。此实现与HashSet的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序
(3)LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

15.HashSet存储自定义类型
(1)HashSet判断元素唯一的原理:看传入对象的hashCode和equal方法

16.Object的hashCode方法
(1).Object的hashCode方法默认
hashCode就是对象地址的10进制
(2).String的hashCode
String重写了hashCode方法让hashoCode和内容相关
(3).我们自定义的类如果要放到HashSet中怎么办?
也要重写hashCode方法

17.Object的equals方法

public class Person {
    private String name;
    private int age;
    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        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;
    }

    // p1.equals(p1)
    // p1.equals(null)
    // p1.equals(new Dog())
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true; // 地址值相同,肯定是同一对象返回true
        if (obj == null)
            return false; // 传入null,肯定不是同一对象,返回false
        if (getClass() != obj.getClass())
            return false; // 如果是不同的类型,返回false
        Person other = (Person) obj;
        if (age != other.age)
            return false; // 年龄不相同,返回false
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false; // 姓名不相同,返回false
        return true; // 姓名年龄相同,返回true
    }

//  @Override
//  public String toString() {
//      return "Person [name=" + name + ", age=" + age + "]";
//  }
}

18.哈希表结构的特点
只要看到类名上带有Hash.说明它底层使用哈希表结构.HashSet底层使用的是哈希表结构
集合

19.哈希表的存储元素过程(HashSet判断元素唯一的原理)
集合

集合
总结:只有存入对象的hashCode相同,equals返回true才不会存储

19.HashSet存储自定义对象

public class Demo13 {

    public static void main(String[] args) {
        HashSet<Student> set = new HashSet<>();

        // 创建学生
        Student s1 = new Student("流川枫", 18, 60);
        Student s2 = new Student("樱木花道", 17, 61);
        Student s3 = new Student("赤木刚宪", 18, 100);
        Student s4 = new Student("晴子", 16, 100);
        Student s5 = new Student("晴子", 16, 100);

        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);
        /*
            我们知道元素要放到HashSet中,add里面1判断hashCode是否相同
            s4和s5都是new出来的对象,s4和s5的地址值不一样,我们Studeng类没有重写hashCode方法,
            就用的是Object的hashCode方法,Object的hashCode和对象的内存地址一样
            s4和s5hashCode不一样,直接存储了

            将姓名,年龄和分数相同的人看做同一人,不存储
            所以我们hashCode和姓名,年龄和分数相关
         */

        for (Student s : set) {
            System.out.println(s);
        }
    }
}
public class Student {
    private String name;
    private int age;
    private double socre;
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Student(String name, int age, double socre) {
        super();
        this.name = name;
        this.age = age;
        this.socre = socre;
    }
    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;
    }
    public double getSocre() {
        return socre;
    }
    public void setSocre(double socre) {
        this.socre = socre;
    }

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

    // alt + shift + s -> hashCode and equals


    // hashCode如果相同,需要比较equals方法,如果一个链表中挂的元素太多,equals会被调用很多次,效率就很低了
    // 所以尽量保证hashCode不相同,直接存储速度快
    // hashCode和内容相关
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        long temp;
        temp = Double.doubleToLongBits(socre);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        return result;

//      return 1;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        System.out.println(this.name + " 和  " + other.name);
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (Double.doubleToLongBits(socre) != Double.doubleToLongBits(other.socre))
            return false;
        return true;
    }
}

====================================================

1.Collections集合工具类
(1)Collections工具类中的方法都是方便操作Collection集合的

(2)常用方法:
*max: 取出最大值
*reverse: 将集合中的元素反转
*shuffle: 随机打乱集合中的元素
*sort: 排序
*binarySearch: 二分/折半查找

2.Arrays数组工具类
(1)Arrays中的方法用来操作数组的
(2)常用方法:
*binarySearch: 二分查找
*sort: 排序
*toString: 将数组中元素的内容转成字符串返回

3.集合转数组
(1)为什么要集合转数组:有时候我们想给别人的数据很多,但是不让别人增加或删除,将集合转成数组.就无法增删
(2)Object[] toArray(): 返回Object类型的数组
(3) < T > T[] toArray(T[] a): 转成指定类型的数组

===============================================
1.Map接口
集合

2.Map接口的特点
(1)将键映射到值的对象
(2)键不能重复,值可以重复
(3) 一个键对应一个值

3.Map的实现类
(1)HashMap: 基于哈希表的 Map 接口的实现, 并允许使用 null 值和 null 键,存储和取出没有顺序
(2)LinkedHashMap: 基于哈希表的 Map 接口的实现, 并允许使用 null 值和 null 键,存储和取出有顺序

4.Map接口中的常用方法
(1)V put(K key, V value) : 如果键不存在,添加元素,添加键和值, 返回值是null,如果键已经存在,修改元素,将后面的值替换前的值, 返回值前面被替换的值

(2)V get(Object key) : 通过key获取到value, 没有找到就返回null

(3)V remove(Object key) : 根据键删除这一对值

(4)int size() : 获取Map集合中元素的大小

(5)void clear() : 清空Map集合

3.Map获取所有的键和所有的值
(1)Map获取所有的键(常用) : Set< K > keySet()

(2)Map获取所有的值(不常用) : Collection< V > values()

4.Map集合遍历-键找值方式
(1)使用keySet

5.Map集合遍历-Entry键值对对象
(1)Entry是Map接口内部的一个接口,实际上我们看成普通的接口就可以,Entry中包含一个键和一个值,相当于结婚证

(2)

public class Demo10 {

    public static void main(String[] args) {
        // Entry中包含一个键和一个值

        HashMap<String, String> hm = new HashMap<>();

        hm.put("黄晓明", "Baby");
        hm.put("梁朝伟", "刘嘉玲");
        hm.put("刘恺威", "杨幂");
        hm.put("老干爹", "老干妈");

        // 1.拿到所有的Entry
        Set<Entry<String, String>> entrySet = hm.entrySet();
        // 2.遍历所有Entry,拿到每个Entry
        for (Entry<String, String> entry : entrySet) {
            // 3.通过Entry就可以拿到键和值
            String key = entry.getKey();
            String value = entry.getValue();

            System.out.println(key + " == " + value);
        }
    }
}
  1. Hashtable和HashMap的区别
    (1).HashMap(常用)
    *HashMap: null可以作为键和值
    *HashMap: 线程不同步,不安全,速度快

    (2).Hashtable(面试会问)
    *Hashtable: null不能作为键和值
    *Hashtable: 线程同步,安全,速度慢

相关标签: arraylist