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
22222
33333
6666666666666".split("
");
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));