Long Luo's Life Notes

每一天都是奇迹

By Long Luo

一个类的定义放在另一个类的定义内部,这就是内部类

先来段代码,对内部类有个直观认识:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class OuterClass {
private String name ;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

class InnerClass{
public InnerClass(){
name = "chenssy";
age = 23;
}
}
}

在这里InnerClass就是内部类。

Java中有4种不同类型的Java内部类,下面我们将一一用实例来介绍:

1. 静态内部类(static nested classes)

关键字static可以修饰成员变量、方法、代码块,还可以修饰内部类,而使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。

静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:

  1. 它的创建是不需要依赖于外围类的。
  2. 它不能使用任何外围类的非static成员变量和方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Outer {
static class Inner {
void go() {
System.out.println(" Inner class reference is: " + this);
}
}
}

public class Test {
public static void main(String[] args) {
Outer.Inner n = new Outer.Inner();
n.go();
}
}

Output:

1
Inner class reference is: com.longluo.java.interview.innerclass.Outer$Inner@15db9742
阅读全文 »

HashMap is very useful when a counter is required.

1
2
3
4
5
6
7
8
HashMap<String, Integer> countMap = new HashMap<String , Integer>();

// ... a lot of a’s like the following
if (countMap.keySet().contains(a)) {
countMap.put(a, countMap.get(a) + 1);
} else {
countMap.put(a, 1);
}

loop through hashmap

1
2
3
4
5
6
7
8
9
10
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + " , Value = " + entry.getValue());
}

2 print hashmap

1
2
3
4
5
6
7
8
9
10
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();

while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();

System.out.println(pairs.getKey() + " = " + pairs.getValue());
it.remove(); // avoids a Concurrent Modification Exception
}
}
阅读全文 »

1. what is inner interface in java?

Inner interface is also called nested interface, which means declare an interface inside of another interface. For example, the Entry interface is declared in the Map interface.

1
2
3
4
5
6
7
public interface Map {
interface Entry {
int getKey();
}
}

void clear();

2. why use inner interface?

There are several compelling reasons for using inner interface: 1. It is a way of logically grouping interfaces that are only used in one place. 2. It increases encapsulation. 3. Nested interfaces can lead to more readable and maintainable code.

One example of inner interface used in java standard library is java.util.Map and Java.util.Map.Entry. Here java.util.Map is used also as a namespace. Entry does not belong to the global scope, which means there are many other entities that are 64

3. HOW INNER INTERFACE WORKS?

Entries and are not necessary Map’s entries. This indicates that Entry represents entries related to the Map.

18.3 how inner interface works? To figure out how inner interface works, we can compare it with nested classes. Nested classes can be considered as a regular method declared in outer class. Since a method can be declared as static or non-static, similarly nested classes can be static and non-static. Static class is like a static method, it can only access outer class members through objects. Non-static class can access any member of the outer class.

18.4. A SIMPLE EXAMPLE OF INNER INTERFACE?

Because an interface can not be instantiated, the inner interface only makes sense if it is static. Therefore, by default inter interface is static, no matter you manually add static or not. 18.4 a simple example of inner interface?

Map.java public int e r f a c e Map {

18.4. A SIMPLE EXAMPLE OF INNER INTERFACE?

int e r f a c e Entry { int getKey ( ) ; } void c l e a r ( ) ; } MapImpl.java public c l a s s MapImpl implements Map { c l a s s ImplEntry implements Map. Entry { public int getKey ( ) { return 0 ; } } @Override public void c l e a r ( ) { / / c l e a r } }

翻译 By Long Luo

本文翻译自 The Interface and Class Hierarchy Diagram of Java Collections ,主要通过一系列简单易懂的图片让你迅速了解Java容器类,容器接口以及类层级关系。

大段文字会看得很烦,图片才是王道!

一、 Collection vs Collections

“Collection”和”Collections”是2个完全不同的概念,在Java容器的类层级图中,“Collection”是一个根接口,但是”Collections”仅仅只是一个提供多种静态方法的类用于操作一些Collection类型。

Collection Vs Collections

二、 Collection的类层级图

下图展示了Collection的类层级图:

java-collection-hierarchy

三、 Map的类层级图

下图是一张Map的类层级图:

MapClassHierarchy

四、 总结

collection summary

五、 代码示例

下面展示容器类的一个代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
List<String> a1 = new ArrayList<String>();
a1.add("Program");
a1.add("Creek");
a1.add("Java");
a1.add("Java");
System.out.println("ArrayList Elements");
System.out.print("\t" + a1 + "\n");

List<String> l1 = new LinkedList<String>();
l1.add("Program");
l1.add("Creek");
l1.add("Java");
l1.add("Java");
System.out.println("LinkedList Elements");
System.out.print("\t" + l1 + "\n");

Set<String> s1 = new HashSet<String>(); // or new TreeSet() will order the elements;
s1.add("Program");
s1.add("Creek");
s1.add("Java");
s1.add("Java");
s1.add("tutorial");
System.out.println("Set Elements");
System.out.print("\t" + s1 + "\n");

Map<String, String> m1 = new HashMap<String, String>(); // or new TreeMap() will order based on keys
m1.put("Windows", "2000");
m1.put("Windows", "XP");
m1.put("Language", "Java");
m1.put("Website", "programcreek.com");
System.out.println("Map Elements");
System.out.print("\t" + m1);

输出如下:

1
2
3
4
5
6
7
8
ArrayList Elements
[Program, Creek, Java, Java]
LinkedList Elements
[Program, Creek, Java, Java]
Set Elements
[tutorial, Creek, Program, Java]
Map Elements
{Windows=XP, Website=programcreek.com, Language=Java}

以上!

翻译 By Long Luo

下面这些问题 Stackoverflow 上关于Java collections提问和讨论最多的问题。在你阅读这些问题之前,有必要先阅读下这篇文章 3分钟速读:图解Java Collections的接口以及类层级关系

1. 什么时候用LinkedList?什么时候用ArrayList?

ArrayList本质上是一个数组。它的元素可以直接通过索引值直接访问。但是如果数组已经满了,那么需要重新分配一个更大的数组并且将全部的元素移动到新的数组需要花费O(n)的时间。当然从现有的数组中增加或者删除一个元素都需要移动现有的元素。这个可能是使用ArrayList中最大的不便之处。

LinkedList是一个双端链表。正因为如此,如果要获取一个链表中间的元素,需要从链表的头部开始查找。另一方面,增加或者删除链表中的元素将会很快,因为只需要在本地修改即可。

下表总结了最快情况下的比较需要耗费时间:

MethodArraylistLinkedList
get(index)O(1)O(n)
add(E)O(n)O(1)
add(E, index)O(n)O(n)
remove(index)O(n)O(n)
Iterator.remove()O(n)O(1)
Iterator.add(E)O(n)O(1)

不管运行时间,当大型列表需要额外考虑内存占用。LinkedList每个node至少需要2个额外的指针用于连接前后2个node。而在ArrayList中只需要数组存储元素值即可。

2. 当遍历容器时,高效等价于移除元素的操作?

最正确的方式就是在遍历容器时用Iterator.remove()去修改一个容器,如下代码所示:

1
2
3
4
5
Iterator<Integer> itr = list.iterator();
while(itr.hasNext()) {
// do something
itr.remove();
}

另外一个非常高频的使用但是不正确的代码是这样的:

1
2
3
for(Integer i: list) {
list.remove(i);
}

运行上面的代码时你会得到一个ConcurrentModificationException。原因是因为一个迭代器自生成之后(在for循环中),用于横贯这个列表。与此同时,这个列表同时也被Iterator.remove()修改了。在Java语言中,当一个线程在修改一个容器时而另外一个线程在遍历它是不允许的。

3. 如何将List转换成int[]?

最快捷的方式可能是用Apache Commons Lang库中的ArrayUtils

1
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));

在JDK中,没有快捷方式。请注意你不能使用List.toArray(),因为那会将列表转换成Integer[]。正确的方式应该是这样的:

1
2
3
4
int[] array = new int[list.size()];
for(int i=0; i < list.size(); i++) {
array[i] = list.get(i);
}
阅读全文 »
0%