Java Container——Collection
为什么要引入数据容器 在书写程序的时候,我们常常需要对大量的对象引用进行管理。为了实现有效的归类管理,我们常常将同类的引用放置在同一数据容器中。由于数据容器中存放了我们随时可能需要使用到的对象引用,所以一般的数据容器要都要能能提供方便的查询、遍历、修改等基本接口功能。早期的OOP语言都通过数组的方式来实现对引用集的集中管理和维护。 但是数组方式下,数组大小需要
为什么要引入数据容器
在书写程序的时候,我们常常需要对大量的对象引用进行管理。为了实现有效的归类管理,我们常常将同类的引用放置在同一数据容器中。由于数据容器中存放了我们随时可能需要使用到的对象引用,所以一般的数据容器要都要能能提供方便的查询、遍历、修改等基本接口功能。早期的OOP语言都通过数组的方式来实现对引用集的集中管理和维护。
但是数组方式下,数组大小需要提前被确定,并不允许修改大小,导致其作为一种灵活的数据容器的能力的功能大为下降。为了方便的利用数据容器进行引用的管理,Java中提供了丰富的数据容器以满足程序员多样化的需求。
分类
java结合类主要有两个接口派生出如下图:
常用集合主要特点及实现方式
(1)set
1)(元素不重复),是没有顺序的。比较元素是否相同是用equls实现的
注意:equals的底层是用==实现的,==比较的是指向值的引用。而引用类型重写了equals方法比较的是具体的值。
2)set的底层是用map实现的,hashSet由hashMap实现
原因:set的值是不可重复的,而map的key值是不可重复的,所以set将值保存到了map的key中,而value存的一个object对象。
3)底层实现源码,以添加元素为例
<span style="font-family: Arial, Helvetica, sans-serif;">public boolean add(E e) {</span>
return map.put(e, PRESENT)==null;
}
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
过程:a)添加元素时先判断存放se中数据的obeject数组(transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;)是否存在,不存在新建一个
b)判断key值是否存在,不存在返回错误
c)计算hashcode,遍历已经存在的数据比较hashcode和key值是否存在,若存在新的值覆盖原来的值,否则新加到数组中
d)向数组中添加数据时判断是否能添加(一般超过75%就不可以),可以就添加。不可以就新建一个
(1)arrayList
1)不是线程安全的,vector是线程安全的。两者都是以数组的形式保存数据的
2)用法
public void testFixArrayList(){
//add()和remove()方法在失败的时候会抛出异常(不推荐)
//它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
Queue<String> queue = new LinkedList<String>();
//添加元素
queue.offer("a");
queue.offer("b");
queue.offer("c");
queue.offer("d");
queue.offer("e");
for(String q : queue){
System.out.println(q);
}
System.out.println("===");
System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
for(String q : queue){
System.out.println(q);
}
System.out.println("===");
System.out.println("element="+queue.element()); //返回第一个元素 ,但不删除
for(String q : queue){
System.out.println(q);
}
System.out.println("===");
System.out.println("peek="+queue.peek()); //返回第一个元素 ,但不删除
for(String q : queue){
System.out.println(q);
}
}
3)放进去是什么类型的取出来强制转换成什么类型,否则会报错
public void testarray(){
ArrayList list = new ArrayList();
list.add("hehda");
list.add(new Integer(1));
String a = (String)list.get(0);
Integer b = (Integer)list.get(1);
System.out.println(a);
System.out.println(b);
}
4)
存放元素的就是一个
object
数组。没生成一个新的数组长度为原来的1.5+1倍,之后将原来数组复制到新的数组中
更多推荐
所有评论(0)