您的位置:首页 > 编程语言 > Java开发

Java--容器(Collection)(一)

2016-03-04 09:31 656 查看
容器这篇,我主要从理论理解角度写的,代码可能偏少,因为集合里的方法太多 了但是这些点都是写代码时应当注意的点。

一、层次结构



学完了面向对象部分,上述图的层次结构应该不生疏了,这里简单的做些说明。

Collection函数库与数组的区别:

1). 数组的容量有限,而Collection库的容量而自己调整;

2). Collection函数库只能用来存放对象,而数组没有这样的限制

Collection库是java中的集合框架,collection接口是这个集合框架中的根接口,Colletction代表一组对象.接口是一种规范.Collection接口是一组允许重复的没有顺序的对象;Collection接口下的set接口(不允许重复,无指定顺序,若重复则会覆盖)和list接口(允许重复,有序);Map接口是一组成对的键-值对象(key-value)不能有重复的key,但可有重复value,通过一个对象找另外一个对象.

二、分别介绍

1 . List的三个实现类

List接口里允许重复和有序



查看源码时我们会发现LinkedList里居然还有索引index,这是因为LinkedList类继承了Collection类

2. Set

Set接口里不允许重复,无指定顺序,若重复则会覆盖

- set接口虽然是Collection的子接口,但是其没有提供额外的方法, 猜想: hashSet类是数组+链表,TreeSet类是树

- TreeSet实现的Set接口,故数据元素不可重复(这里去除重复的方式是比较元素是否等于0,故这里无需重写hashCode和equals方法),另外TreeSet的元素是排序的。(对比:HashSet的元素必须重写hashCode和equals方法)

public class Person {
private String name;// 名称
private int age;// 年龄

public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "姓名:" + name + ", 年龄:" + age + "\n";         }
}

public class TestTreeSet {
public static void main(String[] args) {
Person p1 = new Person("张三", 33);
Person p2 = new Person("李四", 22);
Person p3 = new Person("王五", 44);
Person p4 = new Person("赵六", 66);

// 依次存放到TreeSet容器中,使用排序业务类
TreeSet<Person> persons = new TreeSet<Person>(
new Comparator<Person>(){
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
});
persons.add(p1);
// TreeSet在添加数据的时候一边添加一边排序
// 而Collections.sort方式是在数据添加完后再排序
persons.add(p2);
persons.add(p3);
persons.add(p4);
System.out.println(persons);

// TreeSet数据的更改不会影响排序,因为数据是一边添加一边排序的
p4.setAge(0);
System.out.println(persons);

// TreeSet数据的更改不会影响排序,导致更改可能出现数据的重复,而此时已经无法检测了。
// 因此建议使用TreeSet时不要随意修改数据,此时可以使用final关键字来避免失误
p3.setName("张三");
p3.setAge(33);
}
}

public class Person {
private final String name;// 名称
private final int age;// 年龄

public Person() {
super();
name = null;// 添加了final关键字必须初始化一个值
age = 0;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
// 添加了final关键字,无法提供set方法来修改数据
public String getName() {
return name;
}
public int getAge() {
return age;
}
}


TreeSet确保元素实体可以排序,排序的比较器是public Treeset(Comparator<? super E>comparator)

3 . Map

(1). 底层实现是:数组+链表(例如LinkedList[] arr = new LinkedList[9]);

(2). Java中没有指针,但是可以通过个对象(即创建的节点)的属性来保存相关连接关系,其中key和value都可以是任何引用类型的数据;

(3). hashCode()是根据每个对象的地址生成的一个哈希码,每个对象的地址唯一,所以这个哈希码也唯一;

(4). 对于hashCode()与equals()配套重写的原因说明:java中规定两个对象的内容相同时(即euqals()为true时)其hashCode一定也得相同,所以hashCode和equals方法是得同时重写的;

(5). 重头戏:其子类HashMap和HashTable

常用方法的注意点:

A. put(成对存放)和putAll();

B. get():get()方法是通过equals来进行对象比较的,返回的是Object,转型时必须转型为相应的值的对象类型;

C. remove();

D. containKey(是否包含key),containValue(是否包含value)

HashTable和HashMap的区别

-1. 线程安全性:HashTable中的方法是同步的,而HashMap中的方法在缺省的情况下是非同步的,即HashTable较HashMap是线程安全的。在多线程并发的情况下,HashTable可以直接使用,而HashMap需要自己增加同步处理,即HashMap是Hashtable的轻量级实现。

-2. 继承不同:public class Hashtable extends Dictionary implements Map;

public class HashMap extends AbstractMap implements Map

-3. key-value的null值问题:Hashtable中,key和value都不允许出现null值;而在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即既可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

-4. 遍历方式不同:Hashtable使用了 Iterator;HashMap也使用了Iterator,而由于历史原因,Hashtable还使用了Enumeration的方式 。

-5. 哈希值的使用不同:HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

-6. 扩容方式不同:Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

(6). TreeMap:与Set一样,Map中也有排序的类TreeMap

确保Key可以排序

提供key比较器:public TreeMap(Comparator
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: