《集合、》

集合的理解和好处

1、可以保存任意多个对象
2、提供了一系列方便的操作对象的方法:add 、remove 、set、get等

集合主要是两组<单列集合、双列集合>
collection接口有两个重要的子接口 list set 他们的实现子类都是单列集合
Map接口的实现子类 是双列集合

collection接口继承关系图:

在这里插入图片描述

Map接口继承关系图:

在这里插入图片描述

Collection接口和常用方法

Collection接口实现类的特点

1、Collection实现子类可以存放多个元素、每个元素可以是Object
2、有些Collection的实现类、可以存放多个重复的元素,有的不可以
3、有些Collection的实现类、有些是有序的(list)有些不是有序的(set)
4、Collection接口没有直接的实现子类、是通过它的子接口set和list来实现的

Collection接口的常用方法

add添加单个元素【o.add(XXX)】
remove 删除指定元素
contains查找元素是否存在
size获取元素个数
isEmpty判断是否为空
clear清空
assAll添加多个元素
containsAll查找对个元素是否存在
removeAll删除多个元素

Collection接口遍历元素的方式

1、使用iterator(迭代器)

1、Iterator对象称作迭代器,主要用于遍历Collection集合中的元素
2、所有实现了Collection接口的集合类都有一个Iterator()方法,用于返回一个实现了Iterator接口的对象即返回一个迭代器
3、Iteraror仅适用于集合的遍历

迭代器的执行原理

请添加图片描述

迭代器使用
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Main {

    public static void main(String[] args) {
	// write your code here
        //创建集合对象
        Collection col = new ArrayList();
        //使用集合中的add方法将每一本书加起来
        col.add(new Book("西游记","罗贯中",30));
        col.add(new Book("红楼梦","曹雪芹",23));
        col.add(new Book("线性代数","数学教授",32));
        System.out.println(col);//全部一次性输出

        //下面使用迭代器遍历输出
        //快捷键输出迭代器循环 itit或者 ctrl+j

        Iterator iterator = col.iterator();//先将游标初始化
        while (iterator.hasNext()) {//循环条件是集合的下一个元素不是空(要先调用,下面注意中查看)
            Object book =  iterator.next();//这时将游标指向要拿出的数据,并将它赋给book
            System.out.println("书本:"+book);
        }
        System.out.println("第二次使用迭代器遍历的集合");
        Iterator iterator2 = col.iterator();//在第二次遍历的话 “游标需要初始化”
        while(iterator2.hasNext()){
            Object book2 = iterator2.next();
            System.out.println("book2"+book2);
        }
    }
}
class Book{
    private String BookName;
    private String author;
    private double price;

    public Book(String bookName, String author, double price) {
        BookName = bookName;
        this.author = author;
        this.price = price;
    }

    public String getBookName() {
        return BookName;
    }

    public void setBookName(String bookName) {
        BookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "BookName='" + BookName + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }

}
class add{
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        for (int i = 0; i < 10; i++) {
            arrayList.add(i);
        }
    }
}

注意:使用迭代器遍历是,调用i.next()方法之前必须调用i.hasNext()方法进行检测下一个集合空间是否为空
若不调用,则下一条记录无效,直接调用i.next ()会抛出NoSuchElementExceptio异常

2、使用增强for循环

语法:
for(元素基本类型 元素名 : 集合或者数组名){
//逻辑语句
}

list接口和常用方法

list接口基本介绍

1、list集合类中元素有序(即添加顺序和取出顺序一样)且可重复
2、list集合中的每个元素都有其对应的顺序索引、即支持索引
索引是从零开始的
3、list容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

常用方法

1、add添加元素
2、add(int i,object o):在索引为i的地方添加元素o
3、Boolean addAll(int i ,Collection c):从i位置开始将c中的所有元素添加进来
4、int indexOf(Object o)返回在集合中元素o首次出现的位置
5、int lastIndexOf(Object o)返回在集合中元素o最后一次出现的位置
6、remove(int i)移除指定位置的元素
7、set(int i,Object o)将位置 i 的元素替换为o
8、List subList(int i,int j)返回[i,j)位置的子集合

Arraylist

的注意事项

1 permits all elements,including null ,ArraysList可以加入null,并且可以加入多个
2、Arraylist是由数组来实现数据的储存的
3、ArrayList基本等同于Vector,除了ArrayList是线程不安全的(执行效率高)在多线程情况下。不建议使用ArrayList

底层结构和源码分析

!!自己调试源码!!
1、ArrayList中维护了一个Object类型的数组elementDate
2、当穿创建ArrayList对象时,如果使用的是无参构造器,则初始化elementDate容量为0,第一次添加,则扩容elementDate为10,如果需要再次扩容,则扩容elementDate为1.5倍
3、如果使用的是指定大小的构造器,则初始化elementDate容量为指定大小,如果需要扩容,则直接扩容elementDate为1.5倍

vector底层结构和源码剖析

vector 基本介绍(自己deBug查看源码运行

1、Vector底层也是一个对象数组,protected Object [ ] elementDate ;
2、Vector是线程同步的,即线程安全,Vector类的操作方法带有上synchronized
3、在开发中,需要线程同步安全时,考虑使用Vector

LinkedList的底层操作机制

1、linkedList底层维护了一个双向链表。
2、LinkedList中维护了两个属性 first和last分别指向首节点和尾节点
3、每个节点(Node对象),里面又维护了prev,next。item三个属性,其中通过prev指向前一个。通过next指向后一个节点,最终实现双向链表。
4、所以linkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
模拟一个双向链表

最简单双向链表代码
public class LinkedShow_ {
    public static void main(String[] args) {
        //创建链表的单个节点
        Node jack = new Node("jack");
        Node tom = new Node("tom");
        Node join = new Node("join");
        //将单个节点连接起来
        jack.next = tom;
        tom.prev = jack;
        tom.next = join;
        join.prev = tom;
        //确定头结点和尾节点
        Node first = jack;
        Node last = join;
        //循环输出各个节点的元素
        while (true) {
            //从头结点开始输出
            if (first == null) {
                break;
            }
            System.out.println(first);
            first = first.next;//每次将头结点的指向  向后移动
        }
    }
}

class Node {
    Object item;
    Node next;
    Node prev;
    public Node(Object item) {
        this.item = item;
    }
    @Override
    public String toString() {
        return "Node name = " + item;
    }
}

set接口和常用方法

Set接口基本介绍

1、无序(添加和取出的顺序不一样),没有索引
2、不允许重复元素,所以最多包含一个null

Set接口的常用方法

1、和List接口一样,Set接口也是Collection接口的子接口,因此,常用方法和colliction接口一样

Set的遍历方式

同Collection的遍历方式一样,因为Set接口是Collection接口的子接口
1、可使用迭代器
2、增强for
3、不能使用索引的方式来获取

set接口的实现类的对象(Set接口对象)。不能存放重复的元素,可以添加一个null
set接口对象存放数据时无序的(即添加的顺序和取出的顺序不一定相同)
取出的顺序的顺序虽然不是添加的顺序但是他是固定的

Set接口实现类—HashSet

HashSet实现了set接口,
hashset实际上是hashmap
可以存放null值,只能有一个
hashset不保证元素是有序的,取决于hash确定的索引
不能有重复的元素/对象,(和set接口一样)
在这里插入图片描述
在这里插入图片描述

HashSet练习

在这里插入图片描述

package HashSet_Exercise;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Objects;
@SuppressWarnings({"all"})
public class Main {
    public static void main(String[] args) {
        HashSet LinkedHashSet = new LinkedHashSet();
        LinkedHashSet.add("jflk");
        LinkedHashSet.add("fj");
        LinkedHashSet.add("jflk");


        HashSet hashSet = new HashSet();
        hashSet.add(new Employee("jan", 10,
                new Employee.MyDate(2002, 3, 4)));
        hashSet.add(new Employee("jl", 20,
                new Employee.MyDate(2001, 5, 3)));
        hashSet.add(new Employee("jan", 10,
                new Employee.MyDate(2002, 3, 4)));
        System.out.println("hashSet=" + hashSet);
    }
}

class Employee {
    private String name;
    private int age;

    //静态内部类
    //定义MyDate类
    static class MyDate {
        int year;
        int month;
        int day;

        public MyDate(int year, int month, int day) {
            this.year = year;
            this.month = month;
            this.day = day;
        }
    }

    private MyDate birthday;

    public Employee(String name, int age, MyDate birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    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;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", brithday=" + birthday.year + "," + birthday.month + "," + birthday.day +
                '}';
    }

    //重写equals方法,以判断生日是否相同
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name)
                && Objects.equals(birthday.year, employee.birthday.year)
                && Objects.equals(birthday.month, employee.birthday.month)
                && Objects.equals(birthday.day, employee.birthday.day);
    }

    //重写计算hash值方法
    @Override
    public int hashCode() {
        return Objects.hash(name, birthday.year, birthday.month, birthday.day);
    }
}

Set接口实现类—LinkedHashSet

LinkedHashSet是HashSet的子类
LInkedHashSet底层是一个LInkedHashMap,底层维护了一个 数字+双向链表
LInkedHashSet根据元素的HashCode值来决定元素的存储位置。同时使用链表为何要元素的次序,知识的元素看起来是以插入顺序保存的
LinkedHashSet不允许添加重复元素请添加图片描述

自己调试LInkedHashSet源码查看!!!

Map接口和常用方法[JDK8]

在这里插入图片描述

  1. Map和Collection并列存在,用于保存具有映射关系的数据【Key—value】
  2. Map中的Key和Value可以是任何引用类型的数据,会封装发到HashMap$Node对象中
  3. Map中的Key不允许重复,原因和HashSet一样,
  4. Map中的Value可以重复,
  5. Map的Key可以为null,value也可以为null,注意key为null的情况只能有一个,value为null的情况可以有多个
  6. 常用的String类作为Map的key
  7. Key和value之间存在单向的一对一关系
    请添加图片描述

k-v最后是 HashMap N o d e n o d e = n e w N o d e ( h a s h , k e y , v a l u e , n u l l ) k − v 为了方便程序员的遍历,还会创建 E n t r y S e t 集合,该集合存放的元素类型 E n t r y ,而一个 E n t r y 对象就有 k , v E n t r y S e t < E n t r y < k , v > > 即: t r a n s i e n t S e t < M a p . E n t r y < K , V > > e n t r y S e t e n t r y S e t 中,定义的类型是 M a p . E n t r y ,但实际上存放的还是 H a s h M a p Node node = newNode(hash,key,value,null) k-v为了方便程序员的遍历,还会创建EntrySet集合,该集合存放的元素类型 Entry ,而一个Entry对象就有k,v EntrySet<Entry<k,v> > 即:transient Set<Map.Entry< K ,V > > entrySet entrySet 中,定义的类型是 Map.Entry,但实际上存放的还是 HashMap Nodenode=newNodehashkeyvaluenullkv为了方便程序员的遍历,还会创建EntrySet集合,该集合存放的元素类型Entry,而一个Entry对象就有k,vEntrySet<Entry<kv>>即:transientSet<Map.Entry<KV>>entrySetentrySet中,定义的类型是Map.Entry,但实际上存放的还是HashMapNode这是因为 static class Node < K,V> implements Map.Entry。
当把HashMap$Node对象 存放到entrySet就方便我们遍历
请添加图片描述
请添加图片描述

请添加图片描述

HashMap的六种遍历方式

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 练习
 * 使用HashMap添加的三个员工对象
 * 要求:建:员工ID  值:员工对象
 * 并且遍历显示工资大于18000的员工
 * 员工类:姓名,工资,员工id
 */
public class HashMapExercise_ {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("123", new Worker("123", "小王", 34000));
        map.put("456", new Worker("456", "小李", 1000));
        map.put("789", new Worker("789", "jack", 80000));

        System.out.println("----使用增强for循环-----");
        Set keySet = map.keySet();
        for (Object key : keySet) {
            Worker worker = (Worker) map.get(key);
            if(worker.getSalary()>800){
                System.out.println(worker);
            }
        }

        System.out.println("----使用 EntrySet迭代器遍历----");
        Set entrySet = map.entrySet();
        Iterator iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            Map.Entry entry = (Map.Entry) next;
            Worker worker = (Worker) entry.getValue();
            if (worker.getSalary() > 800)
                System.out.println(entry.getKey() + "_" + entry.getValue());
        }
    }

}

class Worker {
    private String id;
    private String name;
    private double salary;

    public Worker(String id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }
}

Map接口常用方法

put 添加
remove 根据键删除映射关系
get 根据键获取值
size:获取元素个数
isEmpty:判断个数是否为零
clear:清除
containsKey:查找键是否存在
keySet:获取所有的键
entrySet:获取所有关系 k-v
values :获取所有的值

HashMap小结

  1. Map接口的常用实现类:HashMap、Hashtable和propreties
  2. HashMap是Map接口的使用频率最高的实现类
  3. HashMap是以 key_value 对的方式来存储数据的(HashMap$Node类型)
  4. key不能重复,但是值可以重复,允许使用null键和null值
  5. 如果添加的相同的key,则会覆盖原来的key_value。等同于修改value(key不会被替换,value会被替换)
  6. 与HashSet一样,不保证映射的顺序,因为底层还是以值的hash值来决定在table表中的位置
  7. HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized关键字

HashMap底层机制及源码剖析

请添加图片描述

请添加图片描述

HashTable的基本介绍

1、存放的元素是键值对【即K—V】
2、Hashtable的键和值都不能为null
3、hashTable使用方法基本上和HashMap一样
4、HashTable是线程安全的

简单说一下HashTable的底层

在这里插入图片描述

HashMap和HashTable的对比

在这里插入图片描述

Map接口实现类 Properties

1、Properties类继承自Hashtable类并且实现了Map接口,也是一种键值对的形式来保存数据的
2、它的使用特点和Hashtable类似
3、Properties还可以用于xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改

在开发中如何选择集合实现类

  1. 先判断存储的类型,(一组对象【单列】或一组键值对【双列】)

  2. 一组对象【单列】:Collection接口

                               允许重复:List
                               					增删多:LinkedList【底层维护了一个双向链表】
                               					改查多:ArrayList【底层维护了 Object 类型的可变数组】
                            不允许重复:Set
                                               无序:HashSet【底层是HashMap。维护了一个哈希表,即【数组+链表+红黑树】】
                                               排序:TreeSet
                                               插入和取出顺序一致:LinkedHashSet ,维护了数组+双向链表
    
  3. 一组键值对【双列】:Map
    键无序:HashMap【底层是Hash表 jdk7 :数组+链表 jdk8:数组+链表+红黑树】
    建排序:TreeMap
    插入和读取顺序一致:LinkedHashMap
    读取文件:Properties

Collection工具类

  1. Collection是一个操作Map,Set,List等集合的工具类

  2. Collection中提供了一系列静态方法对集合元素进行排序。查询和修改等操作

  3. 排序操作

  4. reverse(List):翻转List中元素的顺序

  5. shuffle(List):对List中元素进行随机排序

  6. sort(List):根据元素的自然顺序对指定的List集合按升序排序

  7. sort(List Comparator)根据指定的Comaratpr产生的顺序对List集合元素进行排序

  8. swap(List,int i,int j):将指定List集合中的i处元素和j处元素及进行交换
    查找 替换

  9. Object max(collection):根据元素的自然排序,返回给定集合中的最大元素

  10. Object max(collection ,Comparator)根据Comparator指定的顺序返回给定集合中的最大元素

  11. Object min(collection)

  12. Object min(collection ,Comparator)

  13. int frequency(Collection,Object):返回指定集合中指定元素出现的次数

  14. void copy(List dest,List src):将src中的内容复制到dest中请添加图片描述

  15. boolean replaceAll(LIst list,Object oldVal,Object newVal):使用新值替换旧值

  16. 请添加图片描述

TreeSet分析``

public class TreeSet_ {
    public static void main(String[] args) {
        //进行数据的自定义有序输出
        TreeSet treeSet = new TreeSet(new Comparator() {
            //匿名内部类以参数形式传入TreeSet的构造其中
            /*

            * public TreeSet(Comparator<? super E> comparator) {//这里传入的属性必须实现Collection接口
            否则会抛出类型转换异常
                    this(new TreeMap<>(comparator));
                    *
            底层其实是将传入的 “比较器”对象赋给了TreeMap的属性 comparator
            public TreeMap(Comparator<? super K> comparator) {
                    this.comparator = comparator;
    }
    }*/
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).compareTo((String) o2);
            }
        });
        /*
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check 类型(可能为空)检查

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        Entry<K,V> parent;
        *   Comparator<? super K> cpr = comparator;//将匿名内部类对象赋值给cpr
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);//动态绑定机制,调用匿名内部类中的比较方式
                if (cmp < 0)//根据返回的值,确定左右指针的指向
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;//这里会将add方法传入的属性进行强制类型转换
                这就是上面说的为什么要必须实现Collection接口(add方法传入的元素必须实现Collection接口)
            do {
                parent = t;
                cmp = k.compareTo(t.key);//进入compareTo方法进行对比确定是否出现相同K的元素
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);compareTo方法返回值是零的话说明存在K值相同元素,进行替换
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)//根据返回值确定指针指向属性的值
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }*/

        treeSet.add("bio");
        treeSet.add("bio");
        treeSet.add("akfgdfh");
        treeSet.add("lljo");
        //根据匿名内部类中的比较方式,以及链表指针的连接顺序进行输出
        System.out.println("treeSet="+treeSet);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值