学习笔记2018-1-7

一、Java集合
1、Deque接口提供了一个典型的实现类: ArrayDeque,从该名称就可以看出,它是一个基于数组实现的双端队列,创建 Deque时同样可指定一个 numElements参数,该参数用于指定 Object数组的长度;如果不指定 numElements参数, Deque底层数组的长度为16。
2、Set与Map之间的关系非常密切。虽然Map中放的元素是key- -value对,Set集合中放的元素是单个对象,但如果我们把key-value对中的 value当成key的附庸:key在哪里, value就跟在哪里。这样就可以像对待Set一样来对待Map了。事实上,Map提供了一个Enty内部类来封装key-value对,而计算Enty存储时则只考虑 Entry封装的key.从Java源码来看Java是先实现了Map,然后通过包装一个所有 value都为null的Map就实现了Set集合。
3、Hashtable和 HashMap存在两点典型区别。Hashtable是一个线程安全的Map实现,但 HashMap是线程不安全的实现,所以 HashMap比Hashtable的性能高一点;Hashtable不允许使用null作为key和value,如果试图把null值放进 Hashtable中,将会引发Nullpointerexception异常;但 HashMap可以使用null作为key或 value,由于 HashMap里的key不能重复,所以 HashMap里最多只有一个 key-value对的key为null,但可以有无数多个 key-value对的 value为null。从 Hashtable的类名上就可以看出它是一个古老的类,它的命名甚至没有遵守Java的命名规范:每个单词的首字母都应该大写。也许当初开发 Hashtable的工程师也没有注意到这一点,后来大量Java程序中使用了 Hashtable类,所以这个类名也就不能改为Hash Table了,否则将导致大量程序需要改写。与 Vector类似的是,尽量少用 Hashtable实现类,即使需要创建线程安全的Map实现类,也无须使用 Hashtable实现类,可以通过后面介绍的 Collections工具类把 HashMap变成线程安全的
4、如果需要使用 Weakhashmap的key来保留对象的弱引用,则不要让该key所引对象具有任何强引用,否则将失去使用 Weakhashmap的意义
5、IdentityHashMap实现类。这个Map实现类的实现机制与 Hash Map基本相似,但它在处理两个key相等时比较独特:在Identity HashMap中,当且仅当两个key严格相等(keyl==key2)时, Identity HashMap才认为两个key相等:对于普通的 Hash Map而言,只要keyl和key2通过 equals方法比较返回true,且它们的 hashCode()值相等即可。
6、Java提供了一个操作Set、List和Map等集合的工具类: Collections,该工具类里提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了将集合对象设置为不可变、对集合对象实现同步控制等方法。
6.1、排序操作
Collections提供了如下几个方法用于对List集合元素进行排序。

static void reverse( List list):反转指定List集合中元素的顺序
static void shuffle( List list)):对List集合元素进行随机排序( (shuffle方法模拟了“洗牌”动作)。
static void sort(List list):根据元素的自然顺序对指定List集合的元素按升序进行排序。static void sort(List list,. Comparator c):根据指定 Comparator产生的顺序对List集合元素进行排序
static void swap( List list,inti,intj):将指定List集合中的i处元素和j处元素进行交换
static void rotate( List list, int distance):当 distance为正数时,将list集合的后 i distance个元素“整体”移到前面;当 distance为负数时,将lit集合的前 distance个元素“整体”移到后面。该方法不会改变集合的长度。

二、类、对象和接口
1、对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个 lambda表达式。这种接口称为函数式接口( functional interface)
■注释:你可能想知道为什么函数式接口必须有一个抽象方法。不是接口中的所有方法都是抽象的吗?实际上,接口完全有可能重新声明 Object类的方法,如 to String或 clone这些声明有可能会让方法不再是抽象的。( Java API中的一些接口会重新声明 Object方法来附加 javadoc注释。 Comparator API就是这样一个例子。)更重要的是,正如6.1.5节所述,在 Java SE8中,接口可以声明非抽象方法。
2、如果设计你自己的接口,其中只有一个抽象方法,可以用 Functionallnterface 注解来标记这个接口。这样做有两个优点。如果你无意中增加了另一个非抽象方法,编译器会产生一个错误消息。另外 Javadoc页里会指出你的接口是一个函数式接口。并不是必须使用注解。根据定义,任何有一个抽象方法的接口都是函数式接口。不过使用@ Functionallnterface注解确实是一个很好的做法。

3、内部类中声明的所有静态域都必须是final。原因很简单,我们希望一个静态域只有一个实例,不过对于每个外部对象,会分别有一个单独的内部类实例。如果这个域不是 final,它可能就不是唯一的。
4、内部类不能有 static方法。Java语言规范对这个限制没有做任何解释。其实也可以允许有静态方法,限制只能访问外围类的静态域和方法就好。显然,Java设计者认为相对于这种复杂性来说,它带来的好处有些得不偿失。
5、初始化块。前面已经讲过两种初始化数据域的方法:
·在构造器中设置值
·在声明中赋值
实际上,Java还有第三种机制,称为初始化块( (initialization block)。在一个类的声明中,可以包含多个代码块。只要构造类的对象,这些块就会被执行。例如,
class Employee{
static int nextid
String name
Double salary:
∥/object block

{
id++
}
public Employee(String n, double s)
{
nane n,
salary s:
}
}
在这个示例中,无论使用哪个构造器构造对象,id域都在对象初始化块中被初始化。首先运行初始化块,然后才运行构造器的主体部分。这种机制不是必需的,也不常见。通常会直接将初始化代码放在构造器中。有时会在面试中见到这种用法:
例如:下面的技巧称为“双括号初始化”( double brace initialization),这里利用了内部类语法。ArrayList list = new ArrayList<>(){{add(“1”);add(“2”)}}等同于
ArrayList list = new ArrayList<>();
list.add(“1”);
list.add(“2”);
6、建立一个与超类大体类似(但不完全相同)的匿名子类通常会很方便。不过,对于 equals方法要特别当心。第5章中,我们曾建议 equals方法最好使用以下测试: if ( i==other)return false;但是对匿名子类做这个测试时会失败。
7、生成日志或调试消息时,通常希望包含当前类的类名,如:System.err.println("Something happened in"+getclass());不过,这对于静态方法不奏效。毕竟,调用 getclass时调用的是 this.,而静态方法没有this。所以应该使用以下表达式:new Object(){}.getClass().getEnclosingClass()// gets class of static method
在这里, new会建立 Object的一个匿名子类的一个匿名对象, getEnclosingClass()则得到其外围类,也就是包含这个静态方法的类。

你可能感兴趣的:(java)