Collection.sort()排序通过泛化实现对所有类型的排序,对于基础类型如int,string,按照字符表,数字大小排序。对于自定义类型,通过实现Comparable接口,重写comparableTo()方法自定义比较大小的方式。也可以使用Comparator外比较器,Comparable接口的方式比实现Comparator接口的耦合性要强一些。
Collection.sort内部调用的是Arrays.sort方法,对于Arrays类,有两个sort方法,sort(Object)和sort(int),前者使用归并排序,后者使用快排。
import java.util.*;
class xd{
int a;
int b;
xd(int a,int b){
this.a=a;
this.b=b;
}
}
public class Main(){
public static void main(String[] args){
xd a=new xd(2,3);
xd b=new xd(4,1);
xd c=new xd(1,2);
ArrayList list=new ArrayList<>();
array.add(a);
array.add(b);
array.add(c);
Collections.sort(array,new Comparator(){
@Override
public int compare(xd o1,xd o2){
if(o1.a>o2.a)
return 1;
else if(o1.a
TreeMap和TreeSet都是Java Collection Framework的两个重要成员,其中TreeMap实现了Map接口,TreeSet实现了set接口。TreeSet底层是通过TreeMap来实现的。二者的实现方式完全一样,而TreeMap的实现就是红黑树算法。
有序集合里的元素可以根据key或index访问,有序集合在属性的增加、删除、修改中拥有较好的性能。
无序集合里的元素只能遍历。
凡是实现set的AbstractSet、CopyOnWriteArraySet、EnumSet、HashSet、LinkedHashSet、TreeSet都是无序的
凡是实现List的AbstractList、ArrayList、LinkedList、Stack、Vector都是有序的
Set是无序的,但是TreeSet可以保证有序。
Java集合大致可以分为Set、List、Queue和Map四种体系。其中Set代表无序,不可重复的集合。List代表有序,可以重复的集合。Map代表映射关系的集合。Java5又增加了Queue体系,代表一种队列集合实现。
Java集合和数组的区别:
数组元素在初始化时指定,意味着只能保存定长的数据。而集合可以保存数量不确定的数据。数组元素既可以保存基本类型的值,也可以是对象。集合里只能保存对象。基本数据类型要转换成对应的包装类才能放入集合类中。
Java集合类之间的继承关系:Java的集合类主要由两个接口派生而出:Collection和Map。
Map实现类用于保存具有映射关系的数据。Map保存的每项数据都是key-value对,也就是由key和value两个值组成。
Iterator可以用来遍历Set和List集合,但是ListIterator只能遍历List。Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
Iterator的安全失败是基于对底层集合做拷贝,它不受源集合上修改的影响。Java.concurrent包下面的所有类都是安全失败的。而快速失败受到源集合修改的影响,Java.util包下面的所有集合类都是快速失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器不会抛出此异常。
Vector:比ArrayList多了个同步机制(Synchronized)
HashTable:HashMap的线程安全版本
Stack:Stack也是线程安全的,继承与Vector
volatile关键字保证了内存可见性,防止指令重排序。volatile并不保证原子性。
十一、Java编写一个会导致死锁的程序
public static void main(String[] args){
final Object a=new Object();
final Object b=new Object();
Thread threadA=new Thread(new Runnable(){
@Override
public void run(){
synchronized(a){
try{
Thread.sleep(5000);
synchronized(b){
Thread.sleep(1000);
System.out.println("锁住b");
}
}
catch(Exception e){
e.printStackTrace();
}
}
});
Thread threadB=new Thread(new Runnable(){
@Override
public void run(){
synchronized(b){
try{
Thread.sleep(5000);
Synchroninzed(a){
Thread.sleep(1000);
System.out.println(“锁住A”);
}catch(Exception e){
e.printStackTrace();
}
});
ThreadA.start();
ThreadB.start();
}
十二、自旋锁、偏向锁、轻量级锁、重量级锁
阻塞操作会导致在用户态和内核态之间切换,严重影响性能。在很多场景下,同步资源的锁定时间很短,为了这一小段时间去切换线程可能会偿失,可以让线程“稍微等待一会”,这就是自旋锁。
无锁、偏向锁、轻量级锁、重量级锁都是针对synchronized的。synchronized是悲观锁,在操作同步资源之前需要给同步资源加锁,这把锁就存在Java对象头里面。
一个线程访问:在大多数情况下,锁总是由一个线程获得,不存在多线程竞争,所以出现了偏向锁。其目标就是在只有一个线程执行同步代码块的情况下能够提高性能
轻量级锁:两个线程交替访问,锁升级,升级为轻量级锁。
重量级锁:多个线程访问,竞争激烈,升级了重量级锁。
十三、