J2SE 8的集合

时间:2022-05-19 16:21:20

List

ArrayList查询效率高LinkedList插入删除效率高


ArrayList

ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("11");
arrayList.add("22"); //1.循环列表
arrayList.iterator().forEachRemaining(n->System.out.println(n));
System.out.println();
arrayList.stream().forEach(n->System.out.println(n));
System.out.println(); //2.remove之前需要调用next()
Iterator<String> iterator = arrayList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next()); //调用remove之前需要先调用next()
iterator.remove();
}
System.out.println(); //3.contains
boolean contains = arrayList.contains("11");
System.out.println(contains); arrayList.add("33");
arrayList.add("44");
arrayList.add("55");
arrayList.add("66");
arrayList.add("77"); //4.removeIf
arrayList.removeIf(x->x.equals("33"));
System.out.println(arrayList.contains("33"));
System.out.println(); //5.toArray
String[] array = arrayList.toArray(new String[arrayList.size()]);
for (String string : array) {
System.out.println(string);
}
System.out.println(); //6.subList and clear
arrayList.subList(1, 2).clear();
arrayList.stream().forEach(n->System.out.println(n)); //7.ArrayList线程不安全,使用下面方法得到线程安全的List
List<String> synchronizedList = Collections.synchronizedList(arrayList); //8.CopyOnWriteArrayList也是线程安全的
CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList<String>(); //9. 得到一个read only的list
List<String> unmodifiableList = Collections.unmodifiableList(arrayList); //10. Array.newInstance 新建Array
String[] arrayString = {"11","22"};
if(arrayString.getClass().isArray()){
    //新建一个空的数组,类型为array的type,size为新传入的
    Object newInstance = Array.newInstance(arrayString.getClass().getComponentType(), 10);
    
    //拷贝
    System.arraycopy(arrayString, 0, newInstance, 0, Math.min(Array.getLength(arrayString), 10));
    System.out.println(newInstance instanceof String[]);    //true
} //11. 排序
Arrays.sort(arrayString);
Collections.sort(arrayList); //12.查找元素
arrayList.indexOf(""); 

Arrays

//1.字符串->数组
String[] splitArray = "11111\r\n22222\r\n33333\r\n6666666666666".split("\r\n");
System.out.println(Arrays.toString(splitArray)); //2.数组转->字符串
String string2 = Arrays.toString(splitArray);
System.out.println(string2); //3.数组->List
List<String> asList = Arrays.asList(new String[]{"aa","bb","cc"});
asList = Arrays.asList("aa","bb","cc");
System.out.println(asList.toString()); //4. 二分法查找
Arrays.binarySearch(splitArray, "");

LinkedList

添加和删除元素比较方便;查找,效率比较低

LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("11");
linkedList.add("22");
linkedList.add("33"); //1.正向遍历列表
ListIterator<String> listIterator = linkedList.listIterator();
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
System.out.println(); //2.反向遍历列表
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous()); //下一次索引的位置
// System.out.println(listIterator.nextIndex());
//前一次索引的位置
// System.out.println(listIterator.previousIndex());
}
System.out.println(); //3.get(i)会从0位置开始找,所以查找很没有效率
//比如foreach,从中找每次都是get(i),那每次都是从0位置开始找,所以效率很低
String string = linkedList.get(3);

Map

最近在阿里java开发手册上看到了这句话:Map/Set 的 key 为自定义对象时,必须重写 hashCode 和 equals。这里Set集合中放入的是String类型,假如我们放入一个自己定义的类实例的时候,比如Person类实例,这时候我们要自己重新hashcode和equal方法,用自己的关键字段来重写,因为当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致;如果不一致,直接加进去;如果一致,再进行equals方法的比较,equals方法如果返回true,表示对象已经加进去了,就不会再增加新的对象,否则加进去

HashMap

可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能

HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("11", null); //1. 当Map中取到的为不存在的值时(指没有对应的key),可以指定defaultValue
System.out.println(hashMap.getOrDefault("11", "Default value 1"));
System.out.println(hashMap.getOrDefault("22", "Default value 2"));
System.out.println(); //2. forEach
hashMap.put("11", "11 value");
hashMap.put("22", "22 value");
hashMap.put("33", "33 value");
hashMap.forEach((k,v)->System.out.println(k+" "+v));
System.out.println(); //3. contains
System.out.println(hashMap.containsKey("11"));
System.out.println(hashMap.containsValue("22 value"));
System.out.println(); //4. 更新值
//(1) 原值没有会得到null值,可以指定初始值
hashMap.put("44", hashMap.getOrDefault("44", "")+"**");
hashMap.forEach((k,v)->System.out.println(k+" "+v));
System.out.println();
//(2) 键存在才会赋值
hashMap.putIfAbsent("55", hashMap.get("55")+"**");
hashMap.forEach((k,v)->System.out.println(k+" "+v));
System.out.println();
//(3) merge, 对于指定的key,用指定的function去添加value==>这样有的值可以不用先取出来,直接append
hashMap.merge("11", " 11 added value", String::concat);
hashMap.forEach((k,v)->System.out.println(k+" "+v));
System.out.println(); //5. KeySet -- key
Set<String> keySet = hashMap.keySet();
keySet.forEach(n->System.out.println(n));
System.out.println(); //6. Collection -- values
Collection<String> values = hashMap.values();
values.forEach(n->System.out.println(n));
System.out.println(); //7. EntrySet -- key & values
Set<Entry<String, String>> entrySet = hashMap.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey()+" "+entry.getValue());
}
System.out.println(); entrySet.forEach((n)->System.out.println(n.getKey()+" "+n.getValue()));
System.out.println(); //8. read only
Map<String, String> unmodifiableMap = Collections.unmodifiableMap(hashMap);

LinkedHashMap

HashMap的双向链表

在迭代访问时发而更快,因为它使用链表维护内部次序

LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();

linkedHashMap.put("44", "444");
linkedHashMap.put("11", "111");
linkedHashMap.put("22", "222");
linkedHashMap.put("33", "333"); linkedHashMap.keySet().forEach(n->System.out.println(n)); linkedHashMap.get("44");
linkedHashMap.keySet().forEach(n->System.out.println(n));

WeakHashMap

当Map中的key不再使用时,需要程序删除对应的key,或者使用WeakHashMap; 垃圾回收相关

Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收

WeakHashMap<String, String> weakHashMap = new WeakHashMap<String, String>();

TreeMap

底层是二叉树数据结构,线程不同步,可用于给Map集合中的键进行排序

TreeMap<String, String> treeMap = new TreeMap<String, String>(String::compareTo);

treeMap.put("22", "11");
treeMap.put("11", "11"); treeMap.entrySet().forEach(n->System.out.println(n.getKey()));

ConcurrentHashMap

并发效率更高的Map,用来替换其他线程安全的Map容器,比如Hashtable和Collections.synchronizedMap

ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();

IdentifyHashMap

使用==代替equals()对“键”作比较的hash map

ArrayMap

ArrayMap是一个<key,value>映射的数据结构,它设计上更多的是考虑内存的优化,内部是使用两个数组进行数据存储,
一个数组记录key的hash值,另外一个数组记录Value值,
它和SparseArray一样,也会对key使用二分法进行从小到大排序,在添加、删除、查找数据的时候都是先使用二分查找法得到相应的index,然后通过index来进行添加、查找、删除等操作,
所以,应用场景和SparseArray的一样,如果在数据量比较大的情况下,那么它的性能将退化至少50%

SparseArray

SparseArray比HashMap更省内存,在某些条件下性能更好,主要是因为它避免了对key的自动装箱(int转为Integer类型),它内部则是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,为了优化性能,它内部对数据还采取了压缩的方式来表示稀疏数组的数据,从而节约内存空间

HashTable

HashMap是Hashtable的轻量级实现,非线程安全的实现他们都实现了map接口,主要区别是HashMap键值可以为空null,效率可以高于Hashtable

Set

最近在阿里java开发手册上看到了这句话:Map/Set 的 key 为自定义对象时,必须重写 hashCode 和 equals。这里Set集合中放入的是String类型,假如我们放入一个自己定义的类实例的时候,比如Person类实例,这时候我们要自己重新hashcode和equal方法,用自己的关键字段来重写,因为当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致;如果不一致,直接加进去;如果一致,再进行equals方法的比较,equals方法如果返回true,表示对象已经加进去了,就不会再增加新的对象,否则加进去


HashSet

HashSet不能装入重复的值

HashSet<String> hashSet = new HashSet<>();

hashSet.add("111");
hashSet.add("111");
hashSet.add("222"); System.out.println(hashSet.size()); hashSet.forEach(n->System.out.println(n));

TreeSet

不重复,有序集合;插入值后,自动排序

注意:此例重写了equals(), hashCode(), compareTo()方法

TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(10);
treeSet.add(10);
treeSet.add(6);
treeSet.add(8);
treeSet.forEach(n->System.out.println(n));
System.out.println(); //需要实现Comparable
TreeSet<Item> treeSet1 = new TreeSet<>();
treeSet1.add(new Item("Tom", 123));
treeSet1.add(new Item("Jack", 123));
treeSet1.add(new Item("Alice", 127));
treeSet1.forEach(n->System.out.println(n));
System.out.println(); //指定一个Comparable
TreeSet<Item> treeSet2 = new TreeSet<>(Comparator.comparing(Item::getDescription));
treeSet2.addAll(treeSet1);
treeSet2.forEach(n->System.out.println(n));
System.out.println();
class Item implements Comparable<Item>{
private String description;
private int partNumber; public Item(String description, int partNumber) {
this.description=description;
this.partNumber=partNumber;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} public int getPartNumber() {
return partNumber;
} public void setPartNumber(int partNumber) {
this.partNumber = partNumber;
} @Override
public String toString() {
return "description:"+description+",partNumber:"+partNumber;
} @Override
public boolean equals(Object obj) {
if(this == obj){
return true;
} if(null==obj){
return false;
} if(getClass()!=obj.getClass()){
return false;
} Item anotherItem = (Item)obj; return Objects.equals(description, anotherItem.getDescription())
&&partNumber==anotherItem.getPartNumber();
} @Override
public int hashCode() {
return Objects.hash(description,partNumber);
} @Override
public int compareTo(Item o) {
int compare = Integer.compare(partNumber, o.partNumber); if(compare!=0){
return compare;
}else{
return description.compareTo(o.getDescription());
}
}
}

其它Collection

PriorityQueue

任务调度,每个任务有优先级;随机加入队列中;启动新任务时,将优先级最高的任务从队列中删除

PriorityQueue<LocalDate> priorityQueue = new PriorityQueue<>();

priorityQueue.add(LocalDate.of(2000, 01, 01));
priorityQueue.add(LocalDate.of(2001, 11, 21));
priorityQueue.add(LocalDate.of(1998, 01, 01)); priorityQueue.forEach(n->System.out.println(n)); //每次删除优先级最高的
priorityQueue.remove();
System.out.println(); priorityQueue.forEach(n->System.out.println(n)); priorityQueue.remove();
System.out.println(); priorityQueue.forEach(n->System.out.println(n));