Java 集合

程序中可能通过数组来保存多个对象,因为数组长度是不可变的。 JDK 中提供了一些特殊的类,这些类 可以存储任何对象,并且长度可变,在java 中这些类被为集合 。集合类位于 java.util 包中。

数组存储的特点:
一旦初始化以后,其长度就确定了。
数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。

数组存储的弊端:
1.一旦初始化以后,其长度就不可修改。
2.数组中提供的方法非常限,对于添加、删除、插入数据等操作,非常不便,同时效率不高。
3.获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
4.数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。

Java集合可分为Collection和Map两种体系

     Collection接口:单列数据,定义了存取一组对象的方法的集合。Collection接口下还有个 

Queue接口、Set接口、List接口
    List:元素有序、可重复的集合
    Set:元素无序、不可重复的集
    Map接口:双列数据,保存具有映射关系“key-value对”的集合


其中:

  Set下有HashSet,LinkedHashSet,TreeSet
  List下有ArrayList,Vector,LinkedList
  Map下有Hashtable,LinkedHashMap,HashMap,TreeMap

|----Collection接口:单列集合,用来存储一个一个的对象
     |----List接口:存储有序的、可重复的数据。  -->“动态”数组
           |----ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
           |----LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
           |----Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储
           
     |----Set接口:存储无序的、不可重复的数据   -->数学概念上的“集合”
           |----HashSet:作为Set接口主要实现类;线程不安全;可以存null值
           		|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


|----Map:双列数据,存储key-value对的数据   ---类似于高中的函数:y = f(x)
     |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
          |----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
                    原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。对于频繁的遍历操作,此类执行效率高于HashMap。
     |----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序,底层使用红黑树
     |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
          |----Properties:常用来处理配置文件。key和value都是String类型

Collection接口

java.util.Collection 是所有单列集合的父接口,因此在Collection中定义了单列集合 List 和
Set 通用的一些方法。
方法声明
功能描述
boolean add(Object o)
向集合中添加一个元素
boolean addAll(Collection c)
增加一个集合(多个元素)
void clear()
清空集合
boolean remove(Object o)
删除集合中的一个对象(元素)
boolean removeAll(Collection c)
删除一个集合(多个元素)
boolean isEmpty()
是不是空的
boolean contains(Object o)
判断集合有没有这个元素
boolean containsAll(Collection c)
判断集合中有没有参数集合
Iterator iterator()
返回一个遍历迭代器
int size()
返回集合的元素个数
@Test
public void test01(){
    //1.add(Object e):将元素e添加到集合coll中
    Collection coll = new ArrayList();
    coll.add(123);//自动装箱
    coll.add(new Date());
    Collection coll1 = new ArrayList();
    coll1.add("CC");
    //addAll(Collection coll1):将coll1集合中的元素添加到当前的集合中
    coll.addAll(coll1);
    //2.size():获取添加的元素的个数
    System.out.println(coll.size());//3
    //调用collection1中的toString()方法输出
    System.out.println(coll);//[123, Sun Jan 31 14:37:52 CST 2021, CC]
    //3.clear():清空集合元素
    coll.clear();
    //4.isEmpty():判断当前集合是否为空
    System.out.println(coll.isEmpty());//true
}
@Test
public void Test02(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(new String("Tom"));
    coll.add(new Person("Jerry",20));
    //5.contains(Object obj):判断当前集合中是否包含obj
    //判断时需要调用obj对象所在类的equals()方法
    System.out.println(coll.contains(new String("Tom")));//true
    System.out.println(coll.contains(new Person("Jerry",20)));//false,重写Person类的equals()后为true
    //containsAll(Collection coll1):判断形参coll1中的所有元素是否都存在于当前集合中。
    Collection coll1 = Arrays.asList(1234,new String("Tom"));
    System.out.println(coll.containsAll(coll1));//true
    //6.remove(Object obj):从当前集合中移除obj元素。移除成功返回true,否则返回false
    System.out.println(coll.remove(123));//true
    System.out.println(coll);//[Tom, Person{name='Jerry', age=20}]
    //removeAll(Collection coll1):从当前集合中移除coll1中所有的元素。(差集)
    coll.removeAll(coll1);
    System.out.println(coll);//[Person{name='Jerry', age=20}]
    Collection a = new ArrayList();
    a.add(123);
    a.add(456);
    a.add(new Person("Jerry",20));
    a.add(new String("Tom"));
    a.add(false);
    //7.retainAll(Collection coll1):交集:获取当前集合和coll1集合的交集,并返回给当前集合
    Collection b = Arrays.asList(123,456,789);
    System.out.println(a.retainAll(b));//true
    System.out.println(a);//[123, 456]
}

@Test
public void Test03(){
    Collection a = new ArrayList();
    a.add(456);
    a.add(new Person("Jerry",20));
    a.add(new String("Tom"));
    //8.equals(Object obj):要想返回true,需要当前集合和形参集合的元素都相同。
    Collection b = new ArrayList();
    b.add(456);
    b.add(new Person("Jerry",20));
    b.add(new String("Tom"));
    System.out.println(a.equals(b));//true
    //9.hashCode():返回当前对象的哈希值
    System.out.println(a.hashCode());//1350934216
    //10.集合 --->数组:toArray()
    Object[] arr = a.toArray();
    //拓展:数组 --->集合:调用Arrays类的静态方法asList()
    List<Object> objects = Arrays.asList(arr);
    System.out.println(objects);
    //注意两个的区别
    List<int[]> ints = Arrays.asList(new int[]{123, 456});
    System.out.println(ints.size());//1,集合将其识别为一个元素
    List<Integer> integers = Arrays.asList(new Integer[]{123, 456});
    System.out.println(integers.size());//2
    //11.iterator():返回Iterator接口的实例,用于遍历集合元素。
}
使用Collection集合存储对象,要求对象所属的类满足:
向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals()。

List接口

List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性地将实现了 List 接口的对象称为 List 集合,本质更像一个动态的数组。
方法描述
void add(int index, Object ele)在index位置插入ele元素
boolean addAll(int index, Collection eles)从index位置开始将eles中的所有元素添加进来
Object get(int index)获取指定index位置的元素
int indexOf(Object obj)返回obj在集合中首次出现的位置
int lastIndexOf(Object obj)返回obj在当前集合中末次出现的位置
Object remove(int index)移除指定index位置(0是第一个元素)的元素,并返回此元素
Object set(int index, Object ele)设置指定index位置的元素为ele
List subList(int fromIndex, int toIndex)返回从fromIndex到toIndex位置的子集合
ArrayList
extends AbstractList<E> implements List<E>
java.util.ArrayList 类是 List 接口的一个实现类,此对象相当于动态的数组。
实例化ArrayList类
//实例化 ArrayList
ArrayList list1 = new ArrayList();
//var list2 = new ArrayList();
List list3 = new ArrayList();
//此方法实例出的对象,是只读的(不能添加 删除 移动位置,优点是能够快速建立集合实例对象)
List list4 = List.of();
//list4.add(10); 此行是错误的,因为List.of() 对象是只读的
String[] arr = {"java","javascript","python","html"};
//此方法实例出的对象,是只读的
List list5 = Arrays.asList(1,2,3);
//list5.add(10);
List list6 = new ArrayList(list5);

ArrayList添加、删除、判断、遍历
import java.util.ArrayList;
import java.util.List;
public class Text1 {
    public static void main(String[] args) {
        //实例化,这们实例化,集合可以添加任何类型的元素 默认是Object
        List list = new ArrayList();
         //添加元素
        list.add(10);
        list.add(5.665);
        list.add("java");
        list.add("mysql");
        list.add(0, "python");
        list.addAll(List.of("html", "css"));
        list.addAll(0, List.of(100, 200, 300, 400, 500));
         //修改元素
        list.set(list.indexOf("python"), "python编程");
         //判断元素
        System.out.println(list.contains(10));
        System.out.println(list.containsAll(List.of("mysql", "java")));
         //判断对象在集合中的索引位置
        System.out.println(list.indexOf(200));
        System.out.println(list.indexOf(20000));
         //判断集合是不是空的
        System.out.println(list.isEmpty());
         //输出集合元素个数
        System.out.println(list.size());
        System.out.println(list);
         //删除元素remove(Object o) remove(int index)
         //此时删除的是索引为10的元素,如果下标没有10就出异常
         //int i = 10;
         //Integer i = 10;
        var oo = list.remove(10);
        System.out.println(oo);
        //删除对象,成功返回布尔true,失败返回false
        var tt = list.remove(Integer.valueOf(10));
        System.out.println(tt);
        //删除子集合
        list.removeAll(List.of(100, "mysql", "java"));
        //清空集合
        //list.clear();
         //集合遍历
        for (Object obj : list) {
            System.out.println(obj);
        }
        for (int i = 0; i < list.size(); i++) {
            System.out.printf("list.get(%d) = %s%n", i, list.get(i));
        }
    }
}

ArrayList泛型使用

//使用泛型,泛型不支持8大基本类型
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<>();
var list3 = new ArrayList<String>();
//泛型不支持基本类型,必须是对象类型,8大基本类型不支持。
//List<int> list4 = new ArrayList<>(); 错误
List<Integer> list5 = new ArrayList<>();
//自动装箱操作,如果没有自动装箱,
list5.add(6);
//list5.add("java"); 错误

ArrayList排序

public class List4 {
public static void main(String[] args) {
//实例声明一个list对象实例
List<Integer> list = new ArrayList<>
(List.of(10,2,0,5,15,11,7,8,11,25));
System.out.println(list);
//Collections 集合工具类
//升序
Collections.sort(list);
System.out.println(list);
//降序
Collections.sort(list,(a,b)->b-a);
System.out.println(list);
//升序
Collections.sort(list,(a,b)->a-b);
System.out.println(list);
//乱序,洗牌
Collections.shuffle(list);
Collections.shuffle(list);
Collections.shuffle(list);
Collections.shuffle(list);
System.out.println(list);
}
}
字符串对象排序
public class List5 {
public static void main(String[] args) {
var list = new ArrayList<>(List.of("java", "c", "go", "c++",
"basic", "python", "sql", "php", "javascript"));
System.out.println(list);
//a-z升序
Collections.sort(list);
System.out.println(list);
//z-a降序
Collections.sort(list,(a,b)->b.compareTo(a));
System.out.println(list);
//乱序,洗牌
Collections.shuffle(list);
Collections.shuffle(list);
Collections.shuffle(list);
System.out.println(list);
//根据字符串升序,进行排序 升序
Collections.sort(list,(a,b)->a.length()-b.length());
System.out.println(list);
//降序
Collections.sort(list,(a,b)->b.length()-a.length());
System.out.println(list);
//洗牌
Collections.shuffle(list);
System.out.println(list);
}
}

自定义类对象
cn.webrx.cn.webrx.Student.java 自定义类
如果对象使用集合工具的排序方法,此类必须实现 Comparable<cn.webrx.Student> 接口,实现
方法
@Override
public int compareTo ( cn . webrx . Student b ) {
// 相当于 a.score - b.score 按对象的成绩升序由小到大
return this . score - b . score ;
}
Student 类完整代码
public class Student implements Comparable<Student> {
    private int id;
    private String name;
    private int score;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

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

    public Student(int id, String name, int score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }

    public Student() {
    }

    @Override
    public int compareTo(Student b) {
        //相当于 a.score - b.score 按对象的成绩升序由小到大
        return this.score - b.score;
    }
}
自定义对象 Student 排序案例代码:

public class Text2 {
    public static void main(String[] args) {
        //定义的集合 泛型使用Student
        List<Student> list = new ArrayList<>(List.of(
                new Student(10, "李四", 55),
                new Student(20, "张三", 25),
                new Student(15, "赵六", 15),
                new Student(22, "张三丰", 88),
                new Student(3, "周强", 76)
        ));
        list.add(new Student(11, "张丽丽", 10));
        //未排序
        System.out.println(list);
        //默认排序 按成绩升序
        Collections.sort(list);
        System.out.println(list);
        //按id降序排序
        Collections.sort(list, (a, b) -> b.getId() - a.getId());
        System.out.println(list);
        //根据姓名升序
        Collections.sort(list, (a, b) -> a.getName().compareTo(b.getName()));
        System.out.println(list);
        //洗牌
        Collections.shuffle(list);
        System.out.println(list);
        //System.out.println(list.get(list.size()-1));
    }
}

LinkedList

extends AbstractSequentialList<E>
LinkedList 同时实 现了 List 接口和 Deque 对口,也就是收它既可以看作一个顺序容器,又可以看作一 个队列(Queue),同时又可以看作一个栈(stack),这样 看来, linkedList 简直就是无敌的,当你需要使 用栈或者队列时,可以考虑用LinkedList, 一方面是因为 Java 官方已经声明不建议使用 Stack 类,更遗憾的是, Java里根本没有一个叫做 Queue 的类(只是一个接口的名字)。关于栈或队列,现在首选是 ArrayDeque , 它有着比LinkedList (当作栈或队列使用时)更好的性能。
对与对于频繁的插入和删除元素操作,建议使用LinkedList类,效率更高
新增方法:
void addFirst(Object obj),在链表头部插入一个元素
void addLast(Object obj),在链表尾部添加一个元素
Object getFirst(),获取第一个元素
Object getlast)(),获取最后一个元素
Object removeFirst(),删除头,获取元素并删除
Object removeLast()删除尾
Linkedlist:双向链表,内部没有声明数组,而是定义了Node类型的frst和last,用于记录首末元素。同时,定义内部类Node,作为 Linkedlist中保存数据的基本结构。Node除了保存数据,还定义了两个变量:
prev变量记录前一个元素的位置
next变量记录下一个元素的位置
LinkedList 是非线程安全的,并发环境下,多个线程同时操作 LinkedList,会引发不可预知的错误

Set接口

Set接口是Collection的子接口,set接口没有提供额外的方法
Set集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set集合中,则添加操作失败。(多用于过滤操作,去掉重复数据)
Set判断两个对象是否相同不是使用==运算符,而是根据equals()方法

 |----Collection接口:单列集合,用来存储一个一个的对象
       |----Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
            |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
                 |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
            |----TreeSet:可以按照添加对象的指定属性,进行排序。

HashSet使用哈希表实现的,元素是无序的。添加、删除操作时间复杂度都是O(1)。


TreeSet内部结构是一个树结构(红黑树),元素是有序的,添加、删除操作时间复杂度为O(log(n)),并且提供了first(), last(), headSet(), tailSet()等方法来处理有序集合。


LinkedHashSet是介于HashSet 和 TreeSet之间,内部是一个双向链表结构,所以它的插入是有序的,时间复杂度是O(1)。

存储的数据特点:
用于存放无序的、不可重复的元素

以HashSet为例说明:

  1. 无序性:不等于随机性。存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的。
  2. 不可重复性:保证添加的元素照equals()判断时,不能返回true.即:相同的元素只能添加一个。

Set接口中没额外定义新的方法,使用的都是Collection中声明过的方法。

HashSet

Hashset是Set接口的典型实现,大多数时候使用Set集合时都使用这个实现类。
HashSet按Hash算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
HashSet具有以下特点:
不能保证元素的排列顺序
HashSet不是线程安全的
集合元素可以是nul
HashSet集合判断两个元素相等的标准:两个对象通过hashCode()方法比较相等,并且两个对象的equals()方法返回值也相等。
对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。

 元素添加过程:(难点)

我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:
如果此位置上没有其他元素,则元素a添加成功。 —>情况1
如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
如果hash值不相同,则元素a添加成功。—>情况2
如果hash值相同,进而需要调用元素a所在类的equals()方法:
equals()返回true,元素a添加失败
equals()返回false,则元素a添加成功。—>情况3
对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储。
JDK 7.0 和JDK 8.0 元素添加的区别:
JDK 7.0 :元素a放到数组中,指向原来的元素。(头插法)
JDK 8.0 :原来的元素在数组中,指向元素a。(尾插法)

TreeSet

是一个有序,可排序的,不可重复元素的集合工具类。

与HashSet集合相比,TreeSet还提供了几个额外方法:

Comparator comparator():如果TreeSet采用了定制顺序,则该方法返回定制排序所使用的Comparator,如果TreeSet采用自然排序,则返回null;
Object first():返回集合中的第一个元素;
Object last():返回集合中的最后一个元素;
Object lower(Object e):返回指定元素之前的元素。
Object higher(Object e):返回指定元素之后的元素。
SortedSet subSet(Object fromElement,Object toElement):返回此Set的子集合,含头不含尾;
SortedSet headSet(Object toElement):返回此Set的子集,由小于toElement的元素组成;
SortedSet tailSet(Object fromElement):返回此Set的子集,由大于fromElement的元素组成;

    1.向TreeSet中添加的数据,要求是相同类的对象。
    2.两种排序方式:自然排序(实现Comparable接口) 和定制排序(Comparator)
        1)自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()方法
        2)定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals()方法
 

Collections接口的工具类
java.util.Collections 工具类,相当于数组对象的工具类 Arrays 工具类
排序操作
1. reverse(List) :反转 List 中元素的顺序
2. shuffle(List) :对 List 集合元素进行随机排序
3. sort(List) :根据元素的自然顺序对指定 List 集合元素按升序排序
4. sort(List,Comparator) :根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
替换 和 查找操作
5. swap(List, int ,int ) :将指定 List 集合中的 i 处元素 和 j 处元素进行交换
6. Object max(Collection) :根据元素的自然顺序,返回给定集合中的最大元素
7. Object max(Collection, Comparator) :根据 Comparator 指定的顺序,返回给集合中的最大
元素
8. Object min(Collection) :根据元素的自然顺序,返回给定集合中的最小元素
9. Object min(Collection, Comparator) :根据 Comparator 指定的顺序,返回给集合中的最大
元素
10. int frequency(Collection,Object) :返回指定集合中指定元素的出现次数
11. void copy(List dest,List src) :将 src 中的内容复制到 dest
注意复制的目标集合的长度必须大于源集合,否则会抛出空指针异常
12. boolean replaceAll(List list,Object oldVal,Object newVal) :使用新值替换 List 对象的所有旧 值

Map接口

Map与Collection并列存在。用于保存具有映射关系的数据:key-value
Map中的key和value都可以是任何引用类型的数据
Map中的key用set来存放,不允许重复,即同一个Map对象所对应的类,须重hashCode()和 equals()方法
常用 String类作为Map的“键”
key和value之间存在单向一对一关系,即通过指定的key总能找到唯一的、确定的value
Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是Map接口使用频率最高的实现类

public interface Map < K , V > {
}

添加、删除、修改、查询方法:

Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等

 HashMap

基本使用

{
    public static void main(String[] args) {
        //没有使用泛型,不推荐
        //Map map = new HashMap();
        //实例化Map对象
        Map<String, Book> map = new HashMap<>();
        //添加元素,添加元素时,如果Key值存在,则覆盖元素
        map.put("b01", new Book(10, "《java程序入门》", 35));
        map.put("b02", new Book(22, "《数据库技术》", 55));
        Book book = new Book(33, "《前端开发》", 30);
        map.put("b02", book);
        //判断
        //判断有没有Key 为 b01 true
        System.out.println(map.containsKey("b01"));
        //判断有没有Key 为 b03 false
        System.out.println(map.containsKey("b03"));
        //判断有没有Value 为 new cn.webrx.Book(33,"《前端开发》",30)
        //System.out.println(map.containsValue(new cn.webrx.Book(33,"《前端开发》",30)));
        System.out.println(map.containsValue(book));
        //编辑,重新设置或修改值
        map.replace("b02", new Book(55, "《java微服务开发实战》", 68));
        //删除清空
        //map.clear();
        //map.remove("b02");
        //获取指定元素 get(String key)
        System.out.println(map.get("b01"));
        System.out.println(map.get("b11"));
        //获取指定key元素,如果不存在,则使用默认值返回对象
        System.out.println(map.getOrDefault("b11", new Book(100, "《入门书 籍》", 35)));

        System.out.println(map.getOrDefault("b02", new Book(100, "《入门书 籍》", 35)));
        //获取map集合的元素个数
        System.out.println(map.size());
        System.out.println(map);
    }
}
HashMap遍历KeySet Values
public class HashMap2 {
    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("bj", "北京");
        map.put("tj", "天津");
        map.put("hn", "河南");
        map.put("sh", "上海");
//第一种遍历方式 keySet()方法返回Set集合
        Set<String> keys = map.keySet();
        for (String k : keys) {
//System.out.println(k);
            System.out.printf("map[\"%s\"] = %s%n", k, map.get(k));
        }
//第二种遍历方式 values() 返回Collection<String> 集合
        Collection<String> values = map.values();
        for (String v : values) {
            System.out.println(v);
        }
//第三种遍历方式 entrySet() 返回一个Set<Map.Entry<String,String>> 集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> e : entries) {
//System.out.println(e);
            System.out.println(e.getKey());
            System.out.println(e.getValue());
        }
//第四种遍历方式 使用迭代器接口Iterator 接口
        Iterator<String> iterator = map.values().iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        Iterator<String> iterator1 = map.keySet().iterator();
        while (iterator1.hasNext()) {
            String key = iterator1.next();
            System.out.println(key);
            System.out.println(map.get(key));
        }
    }
}
以上遍历主要 Iterator 遍历集合方式、 for 循环遍历集合方式, Lambda 遍历集合方式,根据具体需求选 用不同的方式,通过Iterator 方式循环删除数据是安全的, for 方式循环删除数据非安全, Lambda 方式循环 删除 数据非安全,通过Iterator 方式的效率也很高
HashMap不是线程同步,如果需要使用线程并发,可以使用Hashtable对象
Hashtable<K,V> implements Map<K,V>
Hashtable :底层也是哈希表,是同步的,是一个单线程结合,是线程安全的集合,速度慢
HashMap :底层也是哈希表,但是线程不安全的集合,是多线程集合,速度快
HashMap (还有之前学的所有集合):都可以存储 null 键, null
Hashtable :不能存储 null 键, null

        

TreeMap

1. 是一个有序的 key-value 集合,它是通过红黑树实现的。该映射根据其键的自然顺序进行排序,或 者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
2. 是继承了 AbstractMap ,也是以 key-value 集合存储。实现了 NavigableMap 接口,可以支持一系列 的导航方法。
       比如返回有序的 key 集合。实现了 Cloneable 克隆接口。实现了 java.io.Serializable 序列化接口。另外,TreeMap 是非线程同步的。
构造方法
TreeMap() 使用键的自然顺序构造一个新的、空的树映射。
TreeMap(Comparator comparator) 构造一个新的、空的树映射,该映射根据给定比较器进行排序。
TreeMap(Map m) 构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺
序 进行排序。
TreeMap(SortedMap m) 构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射。
TreeMap<String, Integer> tm = new TreeMap<>();
TreeMap<String, Integer> tm = new TreeMap<>((a, b) -> Math.random() > .5 ? 1 :
-1);
TreeMap<String, Integer> tm = new TreeMap<>((a, b) -> a.compareTo(b));
TreeMap<String, Integer> tm = new TreeMap<>(Comparator.reverseOrder());
TreeMap<String, Integer> tm = new TreeMap<>((a,b)->b.compareTo(a));
TreeMap<String, Integer> tm = new TreeMap<>((a,b)->a.compareTo(b));
TreeMap<String, Integer> tm = new TreeMap<>(String::compareTo);
//升序
TreeMap<Double, String> t2 = new TreeMap<>();
//TreeMap<Double, String> t2 = new TreeMap<>(Double::compareTo);
//乱序
//TreeMap<Double, String> t2 = new TreeMap<>((a, b) -> Math.random()>.5 ? 1 :-1);
//降序
//TreeMap<Double, String> t2 = new TreeMap<>((a, b) -> a < b ? 1 : -1);
//升序
//TreeMap<Double, String> t2 = new TreeMap<>((a, b) -> a > b ? 1 : -1);
TreeMap<cn.webrx.Student, String> t3 = new TreeMap<>((a,b)->a.getId()-
b.getId());
//key String
t3.put(new cn.webrx.Student(1,"李四1"),"郑州");
t3.put(new cn.webrx.Student(6,"李四2"),"北京");
t3.put(new cn.webrx.Student(2,"李四3"),"天津");
t3.put(new cn.webrx.Student(33,"李四33"),"上海");
t3.put(new cn.webrx.Student(4,"李四5"),"上海");
System.out.println(t3);
常用方法
方法
说明
public NavigableMap<K,V> descendingMap()
把集合逆序返回
put(K key, V value)
将指定值与此映射中的指定键进行关联
int size()
返回此集合元素的个数
V remove(Object key)
putAll(Map map)
将指定映射中的所有映射关系复制到此映射中
Collection values()
Set keySet()
本质是TreeSet
get(Object key)
Map.Entry<K,V> entrySet()返回Set<Map.Entry<K,V>>
containsKey(Object key)
firstEntry()
返回集合第一个Map.Entry<K,V>
lastEntry()
firstKey()
返回集合第一个元素的 Key
lastKey()
boolean remove(Object key, Object value)
containsValue()

public static void main(String[] args) {
TreeMap<Integer, String> tm = new TreeMap<>();
tm.put(1, "hello1");
tm.put(2, "hello22");
tm.put(3, "hello333");
tm.put(10, "hello10");
tm.put(4, "hello4444");
System.out.println(tm);
//.descendingMap() 返回一个Map 根据key降序,对原来的TreeMap没有改变
Map<Integer,String> t2 = tm.descendingMap();
System.out.println(tm);
System.out.println(t2);
}

Vetcor
java.util.Vecto
Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:
Vector 是同步访问的。(非线程安全、 线程安全 )
Vector 包含了许多传统的方法,这些方法不属于集合框架。
Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。

 

Vector ArrayList 功能是一样的, ArrayList 是非线程安全,在多线程使用中同步操作时,会出现脏 读,Vetctor的各个方法添加了同步锁 synchronized 支持线程 安全。在单线程程序中, ArrayList 使用 的最多,速度快,在多线程编程中,如果线程间在同步数据,应该使用Vector

Hashtable
和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射
Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。
Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外, Hashtable中的映射不是有序的
Hashtable 是线程安全的, HashMap 是非线程安全。如果在单线程 main 线程程序中,使用了线程 安全的工具类,效率就低,根据使用量上来说还是HashMap 使用的多。
集合接口及工具类总结:
Collection 接口
List 接口
ArrayList 动态数组,有序 插入删除速度慢,读取速度
LinkedList 双向链表,插入删除速度快,读取速度慢
Vector 动态数组,线程安全
Set 接口
HashSet 唯一集合,无序
TreeSet 唯一集合,是有序
Map 接口
HashMap K,V 键值对集合,双列集合
TreeMap 根据 key 有序的 map 集合
Hashtable HashMap 一样,双列集合,线程安全
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bridge Fish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值