Java容器

一、容器的概念
Java API所提供的一系列类的实例,用于在程序中存放对象。位于java.util包内。

二、容器框架图
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。

三、容器框架体系

  • 接口:是代表集合的抽象数据类型,例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象。
  • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

四、具体介绍
1. Collection接口
Collection接口定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式。
* Set中的数据对象没有顺序且不可以重复。
* List中的数据对象有顺序且可以重复。

2. Iterator接口
①所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。
②Iterator对象称作迭代器,用以方便地实现对容器内元素的遍历操作。

3. Set接口
①Set接口是Collection接口的子接口,Set接口没有提供额外的方法,但实现Set接口的容器类中的元素是没有顺序的,而且不可重复。
②Set容器可以与数学中“集合”的概念相对应。
③Java API中所提供的Set容器类有HashSet、TreeSet等。

4. List接口
①List接口是Collection的子接口,实现List接口的容器类中的元素是有顺序的,而且可以重复。
②List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
③Java API中所提供的List容器类有ArrayList、LinkedList等。

5. Comparable接口
①所有可以“排序”的类都实现了java.lang.Comparable接口,Comparable接口中只有一个方法:public int compareTo(Object obj); 该方法
返回 0 表示this == obj
返回正数表示this > obj
返回负数表示this < obj
②实现了Comparable接口的类通过实现compareTo方法从而确定该类对象的排序方式。

6. Map接口
①实现Map接口的类用来存储键 — 值对。
②Map接口的实现类有HashMap和TreeMap等。
③Map类中存储的键 — 值对通过键来标识,所以键值不能重复。

五、Auto-boxing/unboxing
在合适的时机自动打包、解包
* 自动将基础类型转换为对象
* 自动将对象转换为基础类型

Integer i = 5;
int j = i;

编译器将其变换为: 
Integer i = Integer.valueOf(5);
int j = i.intValue();

六、如何选择数据结构
衡量标准:读的效率和改的效率
* Array读快改慢
* Linked改快读慢
* Hash两者之间

七、泛型
1. 起因
JDK1.4以前类型不明确:
* 装入集合的类型都被当做Object对待,从而失去自己的实际类型。
* 从集合中取出时往往需要转型,效率低,容易产生错误。
2. 解决办法
在定义集合的时候同时定义集合中对象的类型。
3. 好处
增强程序的可读性和稳定性。
4. 泛型实例
指定集合中对象类型可以在定义Collection的时候指定,也可以在循环时用Iterator指定

import java.util.*;

public class BasicGeneric {
public static void main(String[] args) {
List c = new ArrayList();
c.add("aaa");
c.add("bbb");
c.add("ccc");
for(int i=0; i<c.size(); i++) {
String s = c.get(i);
System.out.println(s);
}

Collection c2 = new HashSet();
c2.add("aaa"); c2.add("bbb"); c2.add("ccc");
for(Iterator it = c2.iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}
}
}

class MyName implements Comparable {
int age;

public int compareTo(MyName mn) {
if(this.age > mn.age) return 1;
else if(this.age < mn.age) return -1;
else return 0;
}
}

5. 泛型方法
泛型方法在调用时可以接收不同类型的参数,根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的<E>)。
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。

6. 泛型方法实例

public class GenericMethodTest {
//泛型方法printArray
public static <E> void printArray(E[] inputArray) {
//输出数组元素
for (E element : inputArray) { //增强for循环
System.out.printf("%s", element);
}
System.out.println();
}

public static void main(String[] args) {
//创建不同类型数组:Integer,Double和Character
Integer[] intArray = {1, 2, 3, 4, 5};
Double[] doubleArray = {1.1, 2.2, 3.3, 4.4};
Character[] charArray = {'H', 'E', 'L', 'L', 'O'};

System.out.println("整型数组元素为:");
printArray(intArray); //传递一个整型数组

System.out.println("\n双精度型数组元素为:");
printArray(doubleArray); //传递一个双精度型数组

System.out.println("\n字符型数组元素为:");
printArray(charArray); //传递一个字符型数组
}
}

八、注意事项
容器类对象在调用remove、contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和hashCode方法;对于自定义的类型,需要重写equals方法和hashCode方法以实现自定义的对象相等规则。
* 相等的对象应该具有相等的hash codes。

发表评论

电子邮件地址不会被公开。 必填项已用*标注