Java集合

Java集合

1、集合接口中主要的接口

集合框架定义了一些接口。本节提供了每个接口的概述:

序号接口描述
1Collection 接口 Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。Collection 接口存储一组不唯一,无序的对象。
2List 接口 List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。List 接口存储一组不唯一,有序(插入顺序)的对象。
3Set Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。Set 接口存储一组唯一,无序的对象。
4SortedSet 继承于Set保存有序的集合。
5Map Map 接口存储一组键值对象,提供key(键)到value(值)的映射。
6Map.Entry 描述在一个Map中的一个元素(键/值对)。是一个 Map 的内部接口。
7SortedMap 继承于 Map,使 Key 保持在升序排列。
8Enumeration 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。

Set和List的区别

    1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
    1. Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>
    1. List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector>

在这里插入图片描述

在这里插入图片描述

2、Collection接口

Collection接口通常情况下不被直接使用,不过Collection接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作,因为List接口和Set接口实现了Collection接口,所以这些方法对List集合和Set集合是通用的。

Collection方法分类

1.修改操作

方法名作用
add()添加单个数据,结果返回布尔值
remove()删除单个数据,结果返回布尔值

2.查询操作

方法名作用
size()返回此集合中的元素数。
isEmpty()如果集合中不包含元素,则返回 true 。
contains()如果此集合包含指定的元素,则返回true。
iterator()以正确的顺序返回该列表中的元素的迭代器。
toArray()正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
toArray(T[])正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。 如果列表适合指定的数组,则返回其中。 否则,将为指定数组的运行时类型和此列表的大小分配一个新数组。

3.批量操作

方法名作用
containsAll(Collection<?>)如果此集合包含指定 集合中的所有元素,则返回true。
addALl(Collection<? extends E>)批量添加
removeALL(Collection<?>)批量删除
removeIF(Predicate<? super E>)条件删除
retainAll(Collection<?>)保留删除
clear()清空集合
stream()返回一个顺序Stream与此集合作为其来源。
parallelStream()返回可能并行的Stream与此集合作为其来源。 该方法允许返回顺序流。
首先看一下添加操作与批量添加操作

定义一个Fruit类,一个Apple类,以及一个Banana类

public class Fruit {
private String name;

public Fruit(String name) {
    this.name = name;
	}
@Override
public String toString() {
    return name;
	}
}
public class Apple extends Fruit{
    public Apple(String name) {
        super(name);
    }
}
public class Banana extends Fruit{
    public Banana(String name) {
        super(name);
    }
}

然后在主方法中写一个集合,并向这个集合中国添加数据

public class Demo01 {
    //首先看一下添加操作boolean add(),添加成功返回True,失败返回False
    public static void main(String[] args) {
        List<Fruit> fruits = new ArrayList<>();
        System.out.println(fruits.add(new Apple("红富士苹果")));
        System.out.println(fruits.add(new Apple("青苹果")));
        System.out.println(fruits.add(new Fruit("蛇果")));
        for (Fruit fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

输出结果:

true
true
true
红富士苹果
青苹果
蛇果 

List fruits = new ArrayList<>();

因为集合中定义的是Fruit,说明该集合只能存储Fruit对象或者Fruit的子类对象

再看一下addall()方法,添加成功返回true,否则返回false

首先定义两个集合,分别为苹果集合和香蕉集合,并向集合中添加数据

public class Demo01 {
    //首先看一下添加操作boolean add(),添加成功返回True,失败返回False
    public static void main(String[] args) {
        List<Apple> apples = new ArrayList<>();
            apples.add(new Apple("红富士"));
            apples.add(new Apple("青苹果"));
            apples.add(new Apple("蛇果"));
        List<Banana> bananas = new ArrayList<>();
        bananas.add(new Banana("帝皇蕉"));
        apples.add(new Apple("海南香蕉"));
        List<Fruit> fruits = new ArrayList<>();
        System.out.println(fruits.addAll(apples));
        System.out.println(fruits.addAll(bananas));
        for (Fruit fruit : fruits) {
            System.out.println(fruit);
        }

}
}
集合删除数据

remove()删除单个数据,删除批量数据removeAll,删除符合添加条件的数据,removeIF,删除所有数据clear,即清空数据!

首先先看单个删除操作如何操作的

public class Demo02 {
    public static void main(String[] args) {
        //定义一个数字集合
        List<Integer> numbers = new ArrayList<>();
                numbers.add(1);
                numbers.add(2);
                numbers.add(3);
                numbers.add(4);
                numbers.add(5);
        for (Integer number : numbers) {
            System.out.print(number+" ");
        }
        System.out.println();
        System.out.println("====分===割===线=====");
              numbers.remove(2);
              numbers.remove(3);
        for (Integer number : numbers) {
            System.out.print(number+" ");
        }
    }
}
1 2 3 4 5 
==========线=====
1 2 4 

可以看到,删除我们打印输出的是1,2,4,可以看到他是先删除的下标为2的数字,然后,后面的数字往前进一个,集合中现在的长度为4,我们再取下标3的数,也就是最后一个数5,打印剩下的数就是1.2.4.

1.removeAll()方法

删除要删除数据中的集合,只要有符合的就执行删除操作

代码示例:

public class Demo03 {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        List<Integer> num=new ArrayList<>();
        num.add(2);
        num.add(3);
        num.add(5);
        num.add(6);
        numbers.removeAll(num);
        for (Integer number : numbers) {
            System.out.print(number+" ");
        }
    }

}

输出:

1  4

2.retainAll()方法,指定要保留的数据集合

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

        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        List<Integer> nums = new ArrayList<>();
        nums.add(2);
        nums.add(4);
        nums.add(6);
        numbers.retainAll(nums);
        System.out.println(numbers);
    }
}

输出:

[2, 4]

可以看到,我们把要保留的数放在第二个集合中,当在需要操作的集合中能找到相应的数据,就将其保留!

3.removeIf()方法

public class Demo05 {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        //指定规则删除集合中的数据
        //Predicate接口主要用来判断一个参数是否符合要求
         boolean result=numbers.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                //删除所有偶数
                return integer%2==0;
            }
        });
         //看是否删除成功
        System.out.println(result);
        //遍历集合
        for (Integer number : numbers) {
            System.out.print(number+" ");
        }
    }

}

输出:

true
1 3 5 

4.clear()方法,清空集合

public class Demo06 {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        System.out.println(numbers);
        numbers.clear();
        System.out.println(numbers);
    }
}

输出:

[1, 2, 3, 4, 5]
[]

一些常见的其他方法

public class Demo07 {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        //集合的元素数
        System.out.println(numbers.size());
        //集合是否为空
        System.out.println(numbers.isEmpty());
        //集合中是否有元素2
        System.out.println(numbers.contains(2));
    }
}

输出:

5
false
true

更多方法,具体的可以查看一下jdk的帮助文档

3、ArrayList

ArrayLisy不但拥有Collection中的方法,还拥有List中的所有方法

特点:

  1. 有序
  2. 可重复
  3. 数据可为null

优点:查询快

缺点:增删慢

1.ArrayList中的构造方法

ArrayList中有三种构造方法

  • public ArrayList() 构造一个初始容量为十的空列表。
  • public ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
  • public ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。

2.ArrayList中的常用方法

方法作用
add(E)添加元素
set(int index,E element)覆盖指定位置的元素
remove(int index)删除指定位置的元素
get(int index)获取指定位置的元素
indexOf(Object o)获取指定位置的索引
iterator()获取迭代器
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合
stream()为集合创建流

4、LinkedList

拥有Collection里面的所有方法,List中的所有方法,Queue中的所有方法,Deque中的所有方法

1.LinkedList中的构造方法

  • LinkedList() 构造一个空列表。
  • LinkedList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。

特点:

  1. 有序
  2. 可重复
  3. 可为null

优点:增删块

缺点:查询慢

2.LinkedList的常用方法:

方法作用
getFirst返回此列表中的第一个元素。
getLast返回此列表中的最后一个元素。
removeFirst从此列表中删除并返回第一个元素。
removeLast从此列表中删除并返回最后一个元素。
add将指定的元素追加到此列表的末尾。
addFirst在该列表开头插入指定的元素。
size返回此列表中的元素数。
clear从列表中删除所有元素。 此呼叫返回后,列表将为空。
contains如果此列表包含指定的元素,则返回true`
listIterator从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。
straem为集合创建流

ArrayList与LinkedList的区别

ArrayLIstLinkedList
数据结构数组链表
查询速度
增删速度
内存空间
应用场景查询较多增删较多

5、HashMap

特点:

1.无序

2.key可以为null,哈希值为0

3.key不可以重复,重复的key,新值会覆盖旧值

优点:增删改查快

缺点:无序

1.HashMap的构造方法:

方法作用
HashMap()构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。
HashMap(int initialCapacity)构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)
HashMap(int initialCapacity, float loadFactor)构造一个空的HashMap具有指定的初始容量和负载因子。
HashMap(Map<? extends K,? extends V> m)HashMap(int initialCapacity, float loadFactor)构造一个新的 HashMap与指定的相同的映射 Map`

2.HashMap中常用的方法:

方法名作用
size返回此地图中键值映射的数量。
isEmpty如果此地图不包含键值映射,则返回 true 。
get返回到指定键所映射的值,或null如果此映射包含该键的映射。
put将指定的值与此映射中的指定键相关联。 如果地图先前包含了该键的映射,则替换旧值。
remove从该地图中删除指定键的映射(如果存在)。
clear从这张地图中删除所有的映射。 此呼叫返回后,地图将为空。
containsKey如果此映射包含指定键的映射,则返回 true 。
keySet返回此地图中包含的键的Set视图。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行中修改映射(除了通过迭代器自己的remov操作),迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.remove,Set.remove,removeAll,retainAll和clear操作。 它不支持add或addAll操作。

其中put与get方法在hashmap中用的最为频繁,在实际开发中,hashmap多用于缓存数据

6、LinkedHashMap

特点:

  1. 有序
  2. key唯一
  3. key为null

优点:有序

LInkedHashMap中常用的方法:

方法作用
put(K,V)添加元素
get(Object)获取指定键的元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键的元素
keyset()以set集合的形式返回所有值
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合

7、TreeMap(二叉树映射)

特点:

  1. 对key有序
  2. 无序
  3. key不可为null
  4. key唯一

优点:对key有序

缺点:无序

keymap的常用方法:

方法作用
put(K,V)添加元素
get(Object)获取指定键的元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键的元素
keyset()以set集合的形式返回所有值
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合
descendingMap倒序遍历

8、HashSet(哈希集合)

特点:

  1. 无序
  2. 值唯一
  3. 值可为null

优点:增删改查快

缺点:无序

1.HashSet的构造方法:

构造方法说明
HashSet()构造一个新的空集合; 背景HashMap实例具有默认初始容量(16)和负载因子
HashSet(Collection<? extends E> c)构造一个包含指定集合中的元素的新集合。
HashSet(int initialCapacity)构造一个新的空集合; 背景HashMap实例具有指定的初始容量和默认负载因子(0.75)
HashSet(int initialCapacity, float loadFactor)构造一个新的空集合; 背景HashMap实例具有指定的初始容量和指定的负载因子。

2.HashSet的常用方法

方法作用
add添加元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键
iteartor迭代器
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合

3.HashSet与HashMap的区别

HashmapHashset
key是key,value是value把key当成value使用,value再用统一的值填充

9、LInkedHashSet(链式哈希集合)

特点:

  1. 有序
  2. 值唯一
  3. 值可位null

优点:有序,增删快

缺点:查询慢

1.LinkedHashSet的常用方法

方法作用
add添加元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键
iteartor迭代器
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合

2.LinkedHahsSet与LinkedHashMap的区别

LinkedHashSetLinkedhashMap
存储方式key是key,value是value把key当成value使用,value再用统一的值填充
排序方式添加顺序 访问顺序添加顺序

10、TreeSet(二叉树集合)

特点:

  1. 无序
  2. 对值排序
  3. 值不可为null
  4. 值唯一

优点:对值排序

缺点:无序

1.TreeSet的常用方法:

方法作用
add添加元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键
iteartor迭代器
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合
descendingIterator倒叙遍历

2.HashSet与TreeSet的对比

HashSetLInkEdHashSetTreeset
添加、查询快添加、修改、删除快;有序只有需要对元素进行排序时使用

快速失败(fail-fast)机制

一种容器保护机制,防止多个线程并发修改同一个容器的内容,如果发生了并发修改的情况就会触发快速失败机制,也就是抛出ConcurrentModificationException(并发修改异常)

eg:

当你在迭代遍历某个容器的过程中国,另一个线程介入其中,并且插入或删除此容器中的某个元素,那么就会出现问题,单线程和多线程同理!

我们看一下代码:

可以看出,我们在下面迭代遍历的同时,进行插入操作

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

public class FailFast {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Iterator<String> iterator = list.iterator();
        list.add("1");
        list.add("2");
        while (iterator.hasNext()){
            System.out.println(iterator.next());}
    }
    }

输出:

Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
	at java.util.ArrayList$Itr.next(ArrayList.java:861)
	at com.gather.map.FailFast.main(FailFast.java:14)

那么为了防止这类问题出现,java容器类采用了快速失败机制,主要用与监视容器的变化

那么如何避免上述问题:我们只需要采用线程安全的容器即可

线程不安全线程安全
ArrayLIstCopyOnWriteArrayList
LinkedList
HashMapConcurrentHashMap
LinkedHashMap
TreeMap
HashSetCopyOnWriteArraySet
LinkedHashSet
TreeSet

代码示例:

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class FailFast2 {
    public static void main(String[] args) {
        //创建一个支持并发的集合
        CopyOnWriteArrayList list=new CopyOnWriteArrayList();
        //另一个线程修改器
        new Thread(new Runnable() {
            @Override
            public void run() {
                list.add("一个简单的多线程");
                list.add("lingstar");
            }
        }).start();
         //获取迭代器
        Iterator<String> iterator = list.iterator();
        //遍历集合
        while (iterator.hasNext()){
            //获取元素
            System.out.println(iterator.next());
        }
    }
}

输出:

一个简单的多线程
lingstar

11、ConcurrentHashMap

特点:

  1. 无序
  2. key唯一
  3. key、value不可为null
  4. 线程安全

优点:增删改查快

缺点:无序

1.ConcurrentHashMap的常用方法

方法作用
put添加元素
get(Object)获取指定键的元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键
keySet()以set集合的形式返回所有键
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合

2.ConcurrentHashMap与HashMap的区别

hashMapConcurrentHahsmap
线程是否安全不安全安全
扩容单线程扩容多线程协同扩容
统计元素个数sizebaseCount+CounterCell()
--------------------------------------------
put添加元素
get(Object)获取指定键的元素
containsKey(Object)查询集合中是否包含指定键
remove(Object)删除指定键
keySet()以set集合的形式返回所有键
size()获取集合大小
isEmpty()判断集合是否为空
clear()清空集合

2.ConcurrentHashMap与HashMap的区别

hashMapConcurrentHahsmap
线程是否安全不安全安全
扩容单线程扩容多线程协同扩容
统计元素个数sizebaseCount+CounterCell()
key,value能否为null不能
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值