目录
一、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》链表结构示意图
2》红黑树结构示意图
红黑树是什么?红黑树特点有哪些?-奇Q工具网对于红黑树你了解多少呢?很多刚刚接触java的人都不知道红黑树是什么,那么下面就一起来看一下红黑树的概念以及它的特点吧!一、什么是红黑树?红黑树,是一种自平衡二叉查找树,是在计算机科学当中,所用到的一种数据结构,最典型的用途就是实现关联数组。红黑树是一种特化的AVL树,也就是平衡二叉树,都是在进行插入和删除操作的的时候,通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。红黑树是复杂的,可是,它的最坏情况运行时间也是非常良好的,并且在实践中是高效的。红黑树可以在O(log n)时间内做查找
https://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:提供一组静态方法操作数组