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

java编程思想(读书笔记):9.持有你的对象

2015-12-11 21:49 253 查看
九、持有你的对象

array(数组):

关于array和其他容器之间的区别,存在两个议题:效率和型别。array是java用来“存储及随机访问一连串对象(尤其是对象的reference)”的各种做法中,最有效率的一种。不过效率带来的牺牲是:当你产生array时,其容量固定且无法动态改变。

其他泛型容器:

包括list,set,,map。他们不会以任何特定的型别来看待它们所持有的对象,一律将持有对象视为Object。只要产生单一容器,便可将任意java对象置于其中(基本性别除外)。基本型别要通过其外覆类进行加载。这引出array比容器好的第二点:当你产生array时,它持有的是特定型别的对象,这意味着编译期的型别检查会防止你将不正确的型别置于array。

array元素的比较:

撰写一份泛型排序码,面临的问题是,排序必须依据对象实际型别来进行比较。当然,为各种不同型别都分别撰写一份排序用的函数,也是一种解决办法,但你应该了解,这种做法无法轻易用在新的型别上。

tips:

程序设计的主要目标,是将“变动的事物和不变得事物隔离开来”。在这里,保持不变的,就是泛用排序算法,会变动的,则是对象的比较法。所以如果你不希望将对象比较动作写死于很多不同的排序函数中,我们可以采用callback技巧。通过callback,“因势而异的程序代码”可被封装于自己的class内,而“永不变动的程序代码”则回头调用前者。通过这个手法,便可让不同的对象各自表述其不同的比较法,并将该比较法喂进同一个排序算法中。

java标准程序库的排序算法,会针对你所排序的型别来进行最佳化。面对基本性别时用的是quicksort,而面对对象则采用stable merge sort。

array排序完毕后,你可以使用Array.binarySearch()快速查找某个元素。但是千万别在未经排序的array身上使用binarySearch,否则结果完全无法预测。

不同容器的基本行为:

list会以元素安插次序来放置元素,不会重新排列或编修。set不接受重复元素,它会使用自己内部的一个排列机制。map也不接受重复元素,重复与否乃是以键值判断的。map排序也是用自己内部的一个机制。

容器的缺点:

如果你在定义容器的时候没有指定容器内存储对象的确切型别,那么你一旦将对象置于容器内,你便损失了他的型别信息。但是当你在定义之初就指定容器存储型别时,它在编译期就可以判断是否型别正确。

例如:

ArrayList<String> list = new ArrayList<String>();
list.add(new Integer(5));


它将会报错。

所谓的“迭代器”,可被用来达成这种概念,迭代器是个对象,其职责便是走访以及选择序列中的一连串对象。

调用java iterator,你可以:

1.调用iterator(),要求容器交给你一个iterator。当你第一次调用iterator的next()时,它会返回序列中的第一个元素。

2.调用next()取得序列中的下一个元素。

3.调用hasnext()检查序列中是否还有其他元素。

4.调用remove()移去迭代器最新传回的元素。

map的机能

“在arraylist中查找key”这个动作并不快,而这正是hashmap提高速度的地方。它不会逐一查找某个key,而会使用一种被称为hash code的特殊值。hash code是一种“将对象内的某些信息转换为几乎独一无二”的int,用来代表那个对象。

代码如下:

package test1;

import java.util.HashMap;

class Counter{
int i = 1;
public String toString(){
return Integer.toString(i);
}
}
public class Statistics {

public static void main(String[] args) {
HashMap hm = new HashMap<>();
for (int i = 0; i < 1000; i++) {
Integer r = new Integer((int)(Math.random()*20));
if(hm.containsKey(r)){
((Counter)hm.get(r)).i++;
}else
{
hm.put(r,new Counter());
}
}
System.out.println(hm);
}
}


这里为什么不使用外覆类呢?因为,使用java的外覆类时,你只能在初始化时设定其值,而后读取其值。换句话说你没有办法在产生外覆类的对象之后改变其值。

持有reference:

java.lang.ref程序库含有一组classes,这些classes为垃圾回收机制提供更大的弹性。当你拥有很多可能耗尽内存的大型对象时,这些classes格外有用。有三个classes继承自抽象类Reference,SoftReference,WeakReference和PhantomReference。他们都对垃圾回收机制提供不同层级的间接性–如果外界只能通过这些Reference对象才得碰触对象的话。

当你虚妄继续持有某个reference(它所指的对象是你希望碰触的),但你也允许垃圾回收器将它释放(回收),这时候你应该使用Reference对象。于是你得以继续使用该对象,而一旦内存即将耗尽,你也允许它被释放。

(代码未写完,待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: