Collection
tps
集合只能存储引用类型 ?这个是疑问点
String :执行操作数据的方式:删除,增加
StringBuffer
数据结构
百度百科说:数据结构是计算机存储、组织数据的方式。 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。
常见的数据结构有:数组、堆和队列、链表、二叉树、红黑树、哈希表及图形
简单排序,递归和进阶排序
Collection
Collection接口是处理对象集合的根接口,其中定义了很多对元素进行操作的方法,AbstractCollection是提供Collection部分实现的抽象类。
LIst 里面的操作
ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
transient Object[] elementData;
ArrayList中用elementData保存数据。底层是Object类型的数组
ArrayList 里面接口定义:
RandomAccess
RandomAccess接口是一个标志接口(Marker),实现了RandomAccess说明,该List接口支持快速随机访问(ArrayList实现了该接口,当遍历时用普通for循环会高效些(该部分会在后续标题Collections中指出),而LinkedList未实现该接口,遍历时用Iterator或者forEach高效些)
Cloneable:
java.io.Serializable:对象的寿命通常随着生成该对象的程序的终止而终止,而有时候需要把在内存中的各种对象的状态(也就是实例变量,不是方法)保存下来,并且可以在需要时再将对象恢复。 Java提供了一种保存对象状态的机制,那就是序列化。
()ArrayList中装载元素的elementData为什么被transient修饰?
transient Object[] elementData; // non-private to simplify nested class access
transient表示这个域不是该对象序列化的一部分,而ArrayList又是可序列化的类,当对象发生序列化,再反序列化,那被transient修饰的字段就会消失。幸好,ArrayLIst还有另一个机制,就是 arrayList在序列化的时候会调用writeObject,直接将size和element写入ObjectOutputStream;反序列化时调用readObject,从ObjectInputStream获取size和element,再恢复到elementData。
ArrayList里面的关键
—LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList 底层是由双向链表组成的List集合,LinkedList的元素添加和删除其实就对应着链表节点的添加和移除
//存储的元素个数
transient int size = 0;
//头节点
transient Node<E> first;
//尾节点
transient Node<E> last;
linkedList 还实现了Deque接口,Deque父接口为Queue,也就是说linkeList 底层还实现了队列。
什么是队列,队列是一种先进先出的数据结构,元素在队列末尾添加,在队列头部删除。Queue接口扩展自Collection,并提供插入、提取、检验等操作。
– Vector
public synchronized boolean addAll(int index, Collection<? extends E> c)
vector里面的方法是用synchronized 修饰的,也就是说该方法是同步的,当发生多线程访问时,可保证数据一致性
@Slf4j
public class ListHH {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("heaan");
arrayList.add("hhh");
arrayList.add(1);
arrayList.add(89);
System.out.println("使用 Iterator进行迭代,现在的list是" + JSON.toJSONString(arrayList));
Iterator iterator = arrayList.iterator();
System.out.println("iterator 对象是" + iterator);
while (iterator.hasNext()) {
Object object = iterator.next();
System.out.println("打印每次进来的元素" + JSON.toJSONString(object));
if ("hhh".equals(object)) {
iterator.remove();
}
log.info("this data is {}",JSON.toJSONString(object));
// log.info("this data is {}", JSON.toJSONString(iterator));// 这段代码被注释掉了。因为保留的话。json.toJSONString(iterator)会将iterator里面的数据全部迭代完毕,导致其他的元素没有接着走hasNext()代码块。
}
log.info("最后打印的data是 {}",JSON.toJSONString(iterator));// 因为hasNext()方法已经把iterator迭代完毕了,所有当 while (iterator.hasNext())代码块跳出的时候,iterator已经是空数组了。
}
}
控制台打印的结果是
使用 Iterator进行迭代,现在的list是["heaan","hhh",1,89]
iterator 对象是java.util.ArrayList$Itr@58651fd0
打印每次进来的元素"heaan"
[23:11:36.422][INFO][com.mmall.ListHH][main] this data is "heaan"
打印每次进来的元素"hhh"
[23:11:36.426][INFO][com.mmall.ListHH][main] this data is "hhh"
打印每次进来的元素1
[23:11:36.427][INFO][com.mmall.ListHH][main] this data is 1
打印每次进来的元素89
[23:11:36.427][INFO][com.mmall.ListHH][main] this data is 89
[23:11:36.449][INFO][com.mmall.ListHH][main] 最后打印的data是 []
map 接口里面的操作
接口定义:
public interface Map<K,V>
– HashMap
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
– HashTable
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable
– LinkedHashMap
public class MapHH {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
System.out.println("通过map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key =" + key + " and value=" + map.get(key));
}
System.out.println("通过map.entrySet使用Iterator遍历key和value");
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println("key=" + entry.getKey() + " and value =" + entry.getValue());
}
System.out.println("使用map.entrySet 遍历key和value");
for (Map.Entry<String, String> entry :
map.entrySet()) {
System.out.println("key=" + entry.getKey() + " and value =" + entry.getValue());
}
System.out.println("通过map.values()遍历所有的value,但是不能遍历key");
for (String v : map.values()
) {
System.out.println("value =" + v);
}
}
}
set里面的操作
HashSet
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
查看散列集HashSet的源码实现可以看到它内部是使用一个HashMap来存放元素的,因为HashSet的元素就是其内部HashMap的键集合,所以所以HashSet可以做到元素不重复。
– LInkedHashSet
LinkedHashSet是继承自HashSet的,支持对规则集内的元素排序。LinkedHashSet中的元素可以按照它们插入规则集的顺序提取
– TreeSet
TreeSet扩展自AbstractSet,并实现了NavigableSet,AbstractSet扩展自AbstractCollection,树形集是一个有序的Set,其底层是一颗树,这样就能从Set里面提取一个有序序列了。在实例化TreeSet时,我们可以给TreeSet指定一个比较器Comparator来指定树形集中的元素顺序。树形集中提供了很多便捷的方法。
数组和集合和字符串之间的转化
字符串转化成数组
String[] s = string.split(","); // 返回数组
数组转化成集合
Arrays.asList(数组); // 返回集合arrayList类型
集合转化成数组
arrayList.toArray();
数组转化成字符串
char类型的数组,可直接使用String.valueOf(数组);
包装数据类型的数组,可借助stringBuffer.append 和遍历。
public class ClassArray {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hhh");
arrayList.add("tengfei");
// 集合转化成数组
String[] strings = arrayList.toArray(new String[arrayList.size()]);
System.out.println("当前数组打印数据是"+String.valueOf(strings)); //输出的是[Ljava.lang.String;@3e3abc88 String.valueOf()方法里面的参数可以是int类型,也可以是Object类型
// 数组转化成字符串
StringBuffer stringBuffer = new StringBuffer();
for (String s :
strings) {
stringBuffer.append(s);
}
// 数组转化成集合
List<String> list = Arrays.asList(strings);
// 字符串转化成集合--- 整体的思想就是字符串先转化成数组,再转化成集合
String a = "a,m,hj";
String[] help = a.split(",");
/* for (String b:
help ) {
System.out.println(b);
}*/
List<String> list1 = Arrays.asList(help);
for (String b : list1
) {
System.out.println(b);
}
char[] chars = {'a','b','c'};
String s= String.valueOf(chars);
System.out.println("char[] 基本数据类型直接用String.valueOf()打印的是abc"+s);
int[] ints ={1,3,5};
String s1 = String.valueOf(ints);
System.out.println("int 基本数据类型直接用String.valueOf打印打印的是[I@6ce253f1"+s1);
}
Collections
collections也是Java util包下的一个包装类,其是服务于collection的一个工具类,包括的方法有集合中元素进行排序、复制、搜索
// for(循环初始值;循环条件;循环参数)
for (String i:linkedList){ } // 该效果等同于下面这句 实际上forEach语句用的就是iterator
for (Iterator iterator = linkedList.iterator();iterator.hasNext();){}
@Test
public void SpeedTest() {
List<String> arrayList = new ArrayList<String>();
for (int i = 0; i < 800000; i++) {
arrayList.add("" + i);
}
long loopTime = CollectionT.traverseByLoop(arrayList);
long iteratorTime = CollectionT.traverseByIterator(arrayList);
log.info("ArrayList比对使用两种方式遍历时间开始,普通for运行的时间为{},iterator或者foreach 运行的时间为{}", loopTime, iteratorTime);
List<String> linkedList = new LinkedList<String>();
for (int i = 0; i < 80000; i++) {
linkedList.add("" + i);
}
long linkLoopTime = CollectionT.traverseByLoop(linkedList);
long linkIteratorTime = CollectionT.traverseByIterator(linkedList);
log.info("LinkedList比对使用两种方式遍历时间开始,普通for运行的时间为{},iterator或者foreach 运行的时间为{}", linkLoopTime, linkIteratorTime);
}
// 使用普通for循环的代码
public static long traverseByLoop(List list) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
list.get(i);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
// 使用迭代器的代码
//使用迭代器遍历
public static long traverseByIterator(List list) {
Iterator iterator = list.iterator();
long startTime = System.currentTimeMillis();
while (iterator.hasNext()) {
iterator.next();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
Arrays
package com.aicai.qa.junit5test.projecttest;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
@Slf4j
public class CollectionT {
ArrayList<String> arrayList;
LinkedList<String> linkedList;
LinkedList<String> stringLinkedList;
HashMap<Integer, String> hashMap;
@BeforeAll
public void init() {
arrayList = new ArrayList<String>();
linkedList = new LinkedList<String>();
stringLinkedList = new LinkedList<>();
hashMap = new HashMap<Integer, String>();
}
@Test
public void testGson() {
Gson gson = new Gson();
int i = gson.fromJson("100", Integer.class);
System.out.println(i);
String a = gson.toJson(false);
System.out.println(a);
}
@org.junit.jupiter.api.Test
public void testArraysCopyOf() {
int[] arr = {1, 2, 3, 4, 5};
int[] copied = Arrays.copyOf(arr, 10);
System.out.println(Arrays.toString(copied));
copied = Arrays.copyOf(arr, 3);// Arrays.copyOf()底层调用了System.arraycopy 不仅仅只是拷贝数组中的元素,在拷贝元素时,会创建一个新的数组对象
System.out.println(Arrays.toString(copied));
}
@Test
public void testArrayList() {
stringLinkedList.add("uuu");// 另一个集合
stringLinkedList.add("hhh");// 另一个集合
linkedList.add("jjj"); // 第二个集合
arrayList.add("hhh");
arrayList.add("uuu");
arrayList.add("yyy");
arrayList.add("xxx");
arrayList.addAll(linkedList);// 添加所有到arrayList
arrayList.remove(1);
System.out.println("arrlist 集合是" + arrayList); // 应该删除uuu
arrayList.remove("xxx");
// log.info(arrayList);
assertAll("校验集合containsAll,contains,get,size方法",
() -> assertEquals("hhh", arrayList.get(0), "校验获取的第一个下标对应数据一致"),
() -> assertTrue(arrayList.containsAll(stringLinkedList), "校验ArrayList是否包含linkedLIst对象"),
() -> assertTrue(arrayList.contains("hhh"), "校验ArrayList是否包含hhh"),
() -> assertEquals(5, arrayList.size()),
() -> assertTrue(!arrayList.isEmpty())
);
for (String s : arrayList
) {
log.info(s);
}
// contains
log.info("arrayList 对象是否存在指定object " + arrayList.contains("hhh"));
// toArray() 转换成数组
String[] strings = arrayList.toArray(new String[arrayList.size()]);// array List的长度和 集合转化成数组
log.info("string 数组是" + JSON.toJSONString(strings));
// Arrays.toList(数组转化成集合)
List<String> list = Arrays.asList(strings);
log.info("list 集合是" + JSON.toJSONString(list));
}
@Test
public void testLinkedList() {
// 链表末尾添加一个新节点
linkedList.add("aa");
// 向链表指定位置添加一个新节点
linkedList.add(1, "bb");
System.out.println("add 后的数据是" + JSON.toJSONString(linkedList));
linkedList.addFirst("cc");// 进栈操作
System.out.println("addFirst 后的数据是" + JSON.toJSONString(linkedList));
linkedList.addLast("dd");// 入队操作
System.out.println("addLast 后的数据是" + JSON.toJSONString(linkedList));// cc aa bb dd
System.out.println(linkedList.removeFirst());// 出队操作
System.out.println("remove 之后的数据是" + JSON.toJSONString(linkedList));
System.out.println(linkedList.getFirst());
System.out.println(linkedList.getLast());
//向链表表尾添加一个新节点
log.info("当前LInkedList 对象是" + JSON.toJSONString(linkedList));
// 删除第一个节点并返回这个节点中的对象
linkedList.removeFirst();
// 删除指定位置的节点,并返回对象
linkedList.remove(1);
// 得到链表第一个节点的对象
log.info(linkedList.getFirst());
// 入队操作
enqueue("hhh", linkedList);
log.info(JSON.toJSONString(linkedList));
// 出队操作
dequeue(linkedList);
log.info(JSON.toJSONString(linkedList));
}
@Test
public void testHashSet() {
// 交集
Set<String> set1 = new HashSet<>(3);
Set<String> set2 = new HashSet<>(3);
set1.add("1");
set1.add("2");
set2.add("1");
set2.add("5");
Set<String> retainAllSet = (Set<String>) retainAll(set1, set2);
Set<String> removeAllSet = (Set<String>) removeAll(set1, set2);
Set<String> addAllSet = (Set<String>) addAll(set1, set2);
log.info("retainAllSet is {}", JSON.toJSONString(retainAllSet));
log.info("removeAllSet is {}", JSON.toJSONString(removeAllSet));
log.info("addAllSet is {}", JSON.toJSONString(addAllSet));
}
@Test
public void testHashMap() {
hashMap.put(1, "一");
hashMap.get(1);
hashMap.get(1);
for (Map.Entry<Integer, String> entry : hashMap.entrySet()) {
}
}
// 入队
private void enqueue(Object e, LinkedList list) {
list.addLast(e);
}
// 出队
private Object dequeue(LinkedList list) {
return list.removeFirst();
}
/**
* 取交集
*
* @param c1
* @param c2
* @return
*/
private Collection<String> retainAll(Collection<String> c1, Collection<String> c2) {
c1.retainAll(c2);
return c1;
}
/**
* 差集
*
* @param c1
* @param c2
* @return
*/
private Collection<String> removeAll(Collection<String> c1, Collection<String> c2) {
c1.removeAll(c2);
return c1;
}
/**
* 并集
*
* @param c1
* @param c2
* @return
*/
private Collection<String> addAll(Collection<String> c1, Collection<String> c2) {
c1.addAll(c2);
return c1;
}
@Test
public void testCollections() {
ArrayList nums = new ArrayList();
nums.add(8);
nums.add(2);
nums.add(9);
nums.add(-2);
System.out.println("arraylist add 之后的数据是" + nums);
Collections.reverse(nums);
System.out.println("reverse 反转后的数据是" + nums);
Collections.sort(nums);
System.out.println("sort 排序按自然排序的升序排序之后的数据是" + nums);
Collections.shuffle(nums);
System.out.println("随机排序之后的数据是" + nums);
//下面只是为了演示定制排序的用法,将int类型转成string进行比较
// System.out.println(nums);
System.out.println("max筛选后的collection集合是" + Collections.max(nums));
System.out.println("min筛选后的collection集合是" + Collections.min(nums));
Collections.replaceAll(nums, -2, -7);
System.out.println("replaceAll 之后的collection是" + nums);
System.out.println("统计元素出现次数是" + Collections.frequency(nums, 2));
Collections.sort(nums);
System.out.println(Collections.binarySearch(nums, 5));
List list = Collections.synchronizedList(nums);// 返回同步的list
}
@Test
public void testArrays() {
}
/**
* 校验randomAccess下 ArrayList和LinkedList遍历的时间。
*/
@Test
public void SpeedTest() {
for (int i = 0; i < 100000; i++) {
arrayList.add("" + i);
linkedList.add("" + i);
}
long loopTime = CollectionT.traverseByLoop(arrayList);
long iteratorTime = CollectionT.traverseByIterator(arrayList);
long linkLoopTime = CollectionT.traverseByLoop(linkedList);
long linkIteratorTime = CollectionT.traverseByIterator(linkedList);
log.info("ArrayList比对使用两种方式遍历时间开始,普通for运行的时间为{},iterator 运行的时间为{}", loopTime, iteratorTime);
log.info("LinkedList比对使用两种方式遍历时间开始,for运行的时间为{},iterator 运行的时间为{}", linkLoopTime, linkIteratorTime);
}
@Test
public void testIsOrNotImplentsRandomAccess() {
ArrayList<String> arrayList = new ArrayList<String>(8);
arrayList.add("hhhh");
arrayList.add("nihao");
traverse(arrayList);
}
public void tests() {
for (String i : linkedList) {
}
for (Iterator iterator = linkedList.iterator(); iterator.hasNext(); ) {
}
}
/**
* 使用for循环遍历
*
* @param list
* @return
*/
public static long traverseByLoop(List list) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
list.get(i);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
//使用迭代器遍历
public static long traverseByIterator(List list) {
Iterator iterator = list.iterator();
long startTime = System.currentTimeMillis();
while (iterator.hasNext()) {
iterator.next();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static void traverse(List list) {
if (list instanceof RandomAccess) {
log.info("实现了RandomAccess接口,不使用迭代器");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
} else {
log.info("没实现RandomAccess接口,使用迭代器");
Iterator it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
@Test
public void testArray() {
String[] s = new String[3];
s[0] = "1";
s[1] = "2";
// s[2]="3";
// Stream.of(s).forEach(s1-> System.out.println(s1));
System.out.println(s.length);
System.out.println(s[0]);
}
}