常用的Java集合框架你知道多少?

目录

一、UML类图

二、List

特点:

遍历:

扩容:

​编辑

如何实现?

1.ArrayList

2.LinkedList

3.Vector

4.CopyOnWriteArrayList

ArrayList remove 的注意点

三、Set

特点:

遍历:

扩容:

实现:

01.HashSet

02.TreeSet

03.排序:

四、Map

特点:

扩容:

遍历:

实现:

01.HashMap

02.HashTable

03.ConcurrentHashMap

04.TreeMap

05.LinkedHashMap


一、UML类图

UML关系图:

注:这是老版,新版还添加了其他的类

UML:统一建模语言

想更好的了解UML可以去这个网址:

UML类图几种关系的总结http://www.uml.org.cn/oobject/201609062.asp


二、List

特点:

元素有序,且可重复

遍历:

下标,foreach,迭代器

扩容:

  • 初始容量10,负载因子0.5,扩容增量0.5倍
  • 新容量 = 原容量 + 原容量 * 0.5  , 如 ArrayList的容量为10,一次扩容后是容量为15

利用反射机制

	@Test
	public void listKuo() throws Exception {
		List<Integer> list=new ArrayList<>();
		for (int i = 0; i <= 100; i++) {
			list.add(i);
			System.out.println("i:"+i);
			System.out.println("len:"+getListEleSize(list));
		}
	}
	
	private int getListEleSize(List obj) throws Exception{
		Class<? extends List> clazz=obj.getClass();
		java.lang.reflect.Field  f=clazz.getDeclaredField("elementData");
		f.setAccessible(true);
		Object[] object= (Object[])f.get(obj);
		return object.length;
	}

如何实现?

1.ArrayList

  • 简单数据结构,超出容量自动扩容,动态数组
  • 内部实现是基于基础的对象数组的
  • 随机访问快(最快)
  • 不适合随机增加或删除
  • 线程不安全

2.LinkedList

  • LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部
  • 线程不安全
  • LinkedList可被用作堆栈(stack)【包括了push,pop方法】,队列(queue)或双向队列(deque)
  • 以双向链表实现,链表无容量限制,允许元素为null,线程不安全
  • 适合做随机的增加或删除

3.Vector

  • 线程安全
  • 并行性能慢,不建议使用

4.CopyOnWriteArrayList

  • 写时复制
  • 线程安全
  • 适合于读多,写少的场景
  • 写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array
  • 比Vector性能高
  • 最终一致性
  • 实现了List接口,使用方式与ArrayList类似

ArrayList remove 的注意点

设置下面这个方法,更方便检查

项目右键找到

点击Add Library中的JUnit,然后点击下一步

 

出现以下界面选择JUnit4,再应用就可以了

用Debug As中的JUnit Test运行

如果正确那么那个长框中就为绿色,错误为红色(如下图)

数据准备:为方便演示,需要有紧挨在一起的两个或多个相同的元素

private List<Integer> list;//成员变量
	
	//每次运行都会执行Before方法
	@Before
	public void setup() {
		list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(3);
		list.add(4);
	}

各种输出方法

	/**
	 * 删除集合中所有为3的元素
	 */
	@Test
	public void remove01() {
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i) == 3)
				list.remove(i);// 错误,因为数组下标会发生改变(移位)
		}
		System.out.println(list);// [1, 2, 3, 4]
	}

	@Test
	public void remove02() {
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i) == 3)
				list.remove(i--);// 正确,删除之后下标往上移了一位,所以又识别到了3
		}
		System.out.println(list);// [1, 2, 4]
	}

	@Test
	public void remove03() {
		for (int i = list.size() - 1; i >= 0; i--) {
			if (list.get(i) == 3) {
				list.remove(i);// 正确,这是从后往前进行检测
			}
		}
		System.out.println(list);// [1, 2, 4]
	}

	@Test
	public void remove04() {
		for (Integer i : list) {
			if (i == 3)
				list.remove(i);// 错误,维护的值不相等了
		}
		System.out.println(list);
	}

	@Test
	public void remove05() {
		// 迭代器
		Iterator<Integer> it = list.iterator();
		while (it.hasNext()) {
			if (it.next() == 3) {
				it.remove();// 正确
			}
		}
		System.out.println(list);
	}

	@Test
	public void remove06() {
		Iterator<Integer> it = list.iterator();
		while (it.hasNext()) {
			Integer value = it.next();
			if (value == 3) {
				list.remove(value);
			}
		}
		System.out.println(list);//错误
	}
	
	@Test
	public void remove07() {
		list.remove(2);//删除下标为2的数
		System.out.println(list);//[1, 2, 3, 4] 
	}

三、Set

特点:

无序,不重复

遍历:

foreach,迭代器

扩容:

初始容量16,负载因子0.75,扩容增量1倍

实现:

01.HashSet

  • 它存储唯一元素并允许空值(依据对象的hashcode来确定该元素是否存在)
  • 由HashMap支持
  • 不保持插入顺序
  • 非线程安全
  • 性能参数:初始容量,负载因子(默认值: 初始容量16,负载因子0.75    示例:new HashSet<>(20, 0.5f);)

示例

package com.pf.dao;

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

import org.junit.Before;
import org.junit.Test;


public class SetDemo {
	
	private List<Integer> list = new ArrayList<>();
	
	private Set<Integer> set = new HashSet<>();
	
	@Before
	public void setup() {
		list.add(1);
		list.add(1);
		list.add(2);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		
		set.add(1);
		set.add(1);
		set.add(2);
		set.add(4);
		set.add(5);
		set.add(3);
	}
	
	/**
	 * 去重
	 */
	@Test
	public void test01() {
		List<Integer> tmp = new ArrayList<>(new HashSet<Integer>(list));
		System.out.println(tmp);
	}
	
	@Test
	public void test02() {
		for(Integer e:set) {
			System.out.println(e);
		}
	}
	
	public void test03() {
		Iterator<Integer> it = set.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}	
	

}

02.TreeSet

  • 是一个包含有序的且没有重复元素的集合
  • 作用是提供有序的Set集合,自然排序或者根据提供的Comparator进行排序
  • TreeSet是基于TreeMap实现的

03.排序:

java.lang.Comparable

java.util.Comparator

第一种:根据sid进行的升序(如果想降序的话,只需要改成o2.getSid()-o1.getSid())

package com.pf.dao;

public class Student {
	
	private Integer sid;
	private String sname;
	private int age;
	public Integer getSid() {
		return sid;
	}
	public void setSid(Integer sid) {
		this.sid = sid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((sid == null) ? 0 : sid.hashCode());
		result = prime * result + ((sname == null) ? 0 : sname.hashCode());
		return result;
	}
	@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;
		if (age != other.age)
			return false;
		if (sid == null) {
			if (other.sid != null)
				return false;
		} else if (!sid.equals(other.sid))
			return false;
		if (sname == null) {
			if (other.sname != null)
				return false;
		} else if (!sname.equals(other.sname))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(Integer sid, String sname, int age) {
		super();
		this.sid = sid;
		this.sname = sname;
		this.age = age;
	}
	
	

}
	private List<Integer> list = new ArrayList<>();
	
	private Set<Integer> set = new HashSet<>();
	
	@Before
	public void setup() {
		list.add(1);
		list.add(1);
		list.add(2);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		
		set.add(1);
		set.add(1);
		set.add(2);
		set.add(4);
		set.add(5);
		set.add(3);
	}

	@Test
	public void test04() {
		TreeSet<Student> stu = new TreeSet<>(new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {//排序
				return o1.getSid()-o2.getSid();
			}
		});
		
		
		stu.add(new Student(1,"zs", 18));
		stu.add(new Student(1,"zs", 18));
		stu.add(new Student(2,"ls", 19));
		stu.add(new Student(4,"lihao", 10));
		stu.add(new Student(7,"lihao", 18));
		stu.add(new Student(5,"zengfanyan", 20));
		stu.add(new Student(3,"we", 30));
		
		//删除
		//stu.remove(new Student(4, "lihao", 10));
		
		for(Student s: stu) {
			System.out.println(s);
		}
	}

效果图:

 第二种:

在实体类(student)中继承一个接口

public class Student implements Comparable<Student>{

然后实现一个方法

	@Override
	public int compareTo(Student o) {
		return this.getSid() - o.getSid();
	}

最后再测试类中把排序删掉

	@Test
	public void test04() {
		TreeSet<Student> stu = new TreeSet<>();
		
		
		stu.add(new Student(1,"zs", 18));
		stu.add(new Student(1,"zs", 18));
		stu.add(new Student(2,"ls", 19));
		stu.add(new Student(4,"lihao", 10));
		stu.add(new Student(7,"lihao", 18));
		stu.add(new Student(5,"zengfanyan", 20));
		stu.add(new Student(3,"we", 30));
		
		//删除
		//stu.remove(new Student(4, "lihao", 10));
		
		for(Student s: stu) {
			System.out.println(s);
		}
	}

四、Map

特点:

无序,键值对,键不能重复,值可以重复,键重复则覆盖,没有继承Collection接口

扩容:

初始容量16,负载因子0.75,扩容增量1倍

遍历:

先获取所有键的Set集合,再遍历(通过键获取值)

取出保存所有Entry的Set,再遍历此Set即可

package com.pf.dao;

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

import org.junit.Before;
import org.junit.Test;

public class MapDemo {
	
	private Map<String, Object> map=new HashMap<String, Object>();
	
	@Before
	public void setup() {
		map.put("1", "zhuzhu");
		map.put("1", "aa");
		map.put("2", "she");
		map.put("3", "he");
		
		//如果键值对没有就添加进去
		map.putIfAbsent("1", "zzz");
	}
	
	@Test
	public void test01() {
		Iterator<String> it = map.keySet().iterator();//通过获取键的集合来获取迭代器
		while(it.hasNext()) {
			String key=it.next();
			System.out.println(map.get(key));
		}
	}
	
	@Test
	public void test02() {
		Iterator<Entry<String, Object>> it = map.entrySet().iterator();
		//比上面的方法略微快一点点,如果对所有的map集合一次遍历完成之后都要去处理的话,就用这种更好
		while(it.hasNext()) {
			Entry<String, Object> e = it.next();
			System.out.println("key = " + e.getKey()+"value = "+e.getValue());
		}
	}

}

实现:

01.HashMap

  • 线程不安全,最常用,速度快
  • 内部采用数组来存放数据

基本原理:

put执行过程

 Table数组中的的Node

1》链表结构示意图

数据结构:链表 - 简书本文内容:1、 什么是链表?2、 链表共分几类?3、 链表的 C 实现! 总表:《数据结构?》 工程代码 Github: Data_Structures_C_Implemen...https://www.jianshu.com/p/73d56c3d228c

2》红黑树结构示意图

红黑树是什么?红黑树特点有哪些?-奇Q工具网对于红黑树你了解多少呢?很多刚刚接触java的人都不知道红黑树是什么,那么下面就一起来看一下红黑树的概念以及它的特点吧!一、什么是红黑树?红黑树,是一种自平衡二叉查找树,是在计算机科学当中,所用到的一种数据结构,最典型的用途就是实现关联数组。红黑树是一种特化的AVL树,也就是平衡二叉树,都是在进行插入和删除操作的的时候,通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。红黑树是复杂的,可是,它的最坏情况运行时间也是非常良好的,并且在实践中是高效的。红黑树可以在O(log n)时间内做查找icon-default.png?t=M5H6https://qqe2.com/java/post/1321.html 可以在下面网站中测试(可以在这个网站学习数据类型)Data Structure Visualization http://www.rmboot.com/注:流程图中绿色标出的部分为JDK8新增的处理逻辑,目的是在Table[i]中的Node节点数量大于8时,通过红黑树提升查找速度。 

02.HashTable

线程安全,不太常用

	@Test
	public void test03() {
		Map<Integer, Object> table = new Hashtable<Integer, Object>();
		table.put(1, "zfm");
		table.put(2, "zfm2");
		table.put(3, "zfm3");
		table.put(4, "zfm4");
		
		Iterator<Integer> it = table.keySet().iterator();
		while(it.hasNext()) {
			int key=it.next();
			System.out.println(table.get(key));
		}
	}

03.ConcurrentHashMap

线程安全,比HashTable性能高(一桶一锁,加强比较并替换操作)

	@Test
	public void test04() {
		Map<Integer, Object> cmap = new ConcurrentHashMap<Integer, Object>();
		cmap.put(1, "zfm");
		cmap.put(2, "zfm2");
		cmap.put(3, "zfm3");
		cmap.put(4, "zfm4");
		
		Iterator<Integer> it = cmap.keySet().iterator();
		while(it.hasNext()) {
			int key=it.next();
			System.out.println(cmap.get(key));
		}
	}

04.TreeMap

  • key值按一定的顺序排序
  • 添加或获取元素时性能较HashMap慢(因为需求维护内部的红黑树,用于保证key值的顺序)

这是降序排列

	@Test
	public void test05() {
		TreeMap<Integer, Object> treeMap = new TreeMap<Integer, Object>(new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				return o2 - o1;
			}
		});
		treeMap.put(1, "zs1");
		treeMap.put(3, "zs3");
		treeMap.put(2, "zs2");
		treeMap.put(4, "zs4");
		
		Iterator<Integer> it = treeMap.keySet().iterator();
		while(it.hasNext()) {
			int key = it.next();        
			System.out.println(treeMap.get(key));
		}
	}

注:如果在new的时候不记得了可以按住Ctrl键再将鼠标移到TreeMap上点击就可以跳转源代码进行查看了

05.LinkedHashMap

  • 继承HashMap
  • LinkedHashMap是有序的,且默认为插入顺序(当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了)
	@Test
	public void test06() {
		Map<String, String> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("name1", "josan1");
        linkedHashMap.put("name2", "josan2");
        linkedHashMap.put("name3", "josan3");
        Set<Entry<String, String>> set = linkedHashMap.entrySet();
        Iterator<Entry<String, String>> iterator = set.iterator();
        while(iterator.hasNext()) {
            Entry entry = iterator.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            System.out.println("key:" + key + ",value:" + value);
        }
	}

工具类

  • Collections:提供一组静态方法操作集合
  • Arrays:提供一组静态方法操作数组

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值