持久对象(编程思想)

持有对象
java中引用太多了,所以使用容器装载。

泛型:
容器中装载不同对象,取出时候强制类型转换容易出错
class Apple {
private static long counter;
private final long id = counter++;
public long id() { return id;}
}
class Orange {}
public class ApplesAndOrangesWithoutGenerics {
public static void main(String[] args) {
ArrayList apples = new ArrayList();
for(int i = 0; i < 3; i++) {
apples.add(new Apple());
apples.add(new Orange());
}
for(int i = 0; i < apples.size(); i++){
((Apple)apples.get(i)).id();
}
}
}
应用预编译得到泛型非常简单,可以在编译器防止将错误类型的对象防止到容器中。
public class ApplesAndOrangesWithGenerics {
public static void main(String[] args) {
ArrayList<Apple> apples = new ArrayList<Apple>();
for(int i = 0; i < 3; i++){
apples.add(new Apple());
// apples.add(new Orange()); 编译报错
}
for(Apple apple : apples){
System.out.println(apple.id());
}
}
}
当你指定了某个类型作为泛型参数时,你并不仅限于只能将该确切类型的对象放置到容器中。向上转型也可以像作用于其他类型一样作用于泛型。

基本概念
java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
Collection。一个独立元素的序列。List按照插入的顺序保存元素、Set不可重复,无序、Queue队列
Map 一组成对的“键值对”对象,允许你使用键来查找值。映射表允许我们使用另一个对象来查找某个对象,它也被称为“关联数组”,因为它将某些对象与另外一些对相关联在了一起;或者被称为“字典”,因为你可以使用键对象来查找值对象,就像在字典中使用单词来定义一样。

Colction.add()
Collection.addAll()
Collections.addAll()
Arrays.asList();
如果使用Arrays.asList()的输出,将其当做List,但是在这种情况下,其底层表示的是数组,因此不能调整尺寸。如果尝试使用add()或者delete()在这种列表中添加或者删除元素,就可能引发去改变数组尺寸的尝试
class Snow {}
class Powder extends Snow {}
class Light extends Powder {}
class Heavy extends Powder {}
class Crusty extends Snow {}
class Slush extends Snow {}
public class AsListInference {
public static void main(String[] args) {
List<Snow> snow1 = Arrays.asList(new Crusty(), new Slush(), new Powder());
// List<Snow> snow2 = Arrays.asList(new Light(), new Heavy());
List<Snow> snows3 = new ArrayList<Snow>();
Collections.addAll(snows3, new Light(), new Heavy());

List<Snow> snows4 = Arrays.<Snow>asList(new Light(), new Heavy());
}
}
可以像操作snows4的操作中所看到的,在Arrays.asList()中间插入一条"线索",以告诉编译器对于Arrays.asList()产生的List类型,实际的目标类型应该是什么。

List:
List承诺可以将元素维护在特定的序列中。List接口在Collection的基础上添加了大量的方法,使得可以在List的中间插入和移除元素。
ArrayList:
LinkedList
constains()
remove()
indexOf()
equals()
优化是一个很棘手的问题,最好的策略就是置之不顾,指导你发现需要担心它了。
subList()允许你从较大的列表中创建出一个片段,而将其结果传递给这个较大的列表的containsAll()方法时,自然会得到true。
Collections.sort()
Collections.shuffle()
retainAll()有效的交集操作,依赖于equals方法。
removeAll()
set(),在指定的索引处,用第二个参数替换整个位置的元素
isEmpty()
clear()

迭代器
对于List,add()是插入元素的方法之一,get()是取出元素的方法之一
使用容器,必须对容器的确切类型编程。考虑在下面的情况:如果原本是对着List编码的,但是后来发现如果能够把相同的代码应用于Set,将会显得非常方便,此时怎么做?
迭代器的概念可以用于达成此目的,迭代器是一个对象,它的工作是遍历并选择序列中的对象,而客户端程序员不必知道或关心序列底层的结构。此外,迭代器通常被称为轻量级对象:创建它的代价小。
iterator()容器返回一个Iterator
next()获得序列中的下一个元素
hasNext()间插序列中是否还有元素
remove()移除由next()产生的最后一个元素
ListIterator
只能用于各类List的访问,ListIterator可以双向移动
LinkedList添加了可以作用于栈、队列或双端队列的方法
Stack可以内部包含一个LinkedList来完成模拟,util包里面的Vector是集成Vector实现的。

Set不保存重复的元素。Set无需,这是因为HashSet使用散列,TreeSet将元素存储在红-黑树数据结构中,HashSet使用的是散列函数,LinkedHashList因为查询速度的原因也使用了散列,但是看起来它使用链表来维护元素的插入顺序。
排序使用TreeSet
contains可以判断数据是否处于容器内
Queue
先进先出的容器
offer()将一个元素插入到队尾
peek()和element()在不移除的情况下返回队头,peek()在队列为空时返回null,element()抛出NoSuchElementException异常
pool和remove()移除并返回队头。为空的情况下前者返回null,后者抛异常
PriorityQueue
典型的队列规则是下一个元素应该是等待时间最长的元素。这个是优先级队列
优先级队列声明下一个弹出元素是最需要的元素(具有最高的优先级)。
PriorityQueue上调用offer()方法来插入一个对象时,这个对象会在队列中被排序。默认的排序将使用对象在队列中的自然排序,但是你可以通过提供自己的Comparator来修改这个排序。

public class PriorityQueueDemo {
public static void main(String[] args) {
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>();
Random rand = new Random(47);
for(int i = 0; i < 10; i++){
priorityQueue.offer(rand.nextInt(i + 10));
}
printQueue(priorityQueue);

List<Integer> ints = Arrays.asList(25, 22, 20, 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25);
priorityQueue = new PriorityQueue<Integer>(ints);
printQueue(priorityQueue);

priorityQueue = new PriorityQueue<Integer>(ints.size(), Collections.<Integer>reverseOrder());
priorityQueue.addAll(ints);
printQueue(priorityQueue);

String fact = "EDUCATION SHOULD ESCHEW OBFUSCATION";
List<String> strings = Arrays.asList(fact.split(" "));
PriorityQueue<String> stringsPQ = new PriorityQueue<String>(strings);
printQueue(stringsPQ);

stringsPQ = new PriorityQueue<String>(strings.size(), Collections.<String>reverseOrder());
stringsPQ.addAll(strings);
printQueue(stringsPQ);
}

public static <T> void printQueue(Queue<T> queue){
for(T obj : queue){
System.out.print(obj + " ");
}
System.out.println();
}
}
Foreach与迭代器
目前为止,foreach语法主要用于数组,但是它也可以应用于任何Collection对象。
public class ForeachCollections {
public static void main(String[] args) {
Collection<String> cs = new LinkedList<String>();
Collections.addAll(cs, "Take the long way home".split(" "));
for(String s : cs){
System.out.print("‘" + s + "‘ ");
}
}
}
Foreach之所以能工作,是因为Java SE5引入了新的被称为Iterable的接口,该接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动。因此如果你创建了任何实现Iterator的类,都可以将它用于forEach语句中。
public class IterableClass implements Iterable<String>{
protected String[] words = "And that is how we know the Earth to be banana-shaped.".split(" ");

public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < words.length;
}

@Override
public String next() {
return words[index++];
}

public void remove() {
throw new UnsupportedOperationException();
}
};
}

public void forEach(Consumer<? super String> action) {

}

public Spliterator<String> spliterator() {
return null;
}

public static void main(String[] args) {
ArrayList al = new ArrayList();
for(String s : new IterableClass()){
System.out.println(s + " ");
}
}
}
iterator()方法返回的是实现了Iterator<String>的匿名内部类的实例,该匿名内部类可以遍历数组中的所有单词。在main中可以发现IterableClass确实可以用于foreach语句中。
foreach语句可以用于数组或者其他任何Iterable,但是这并不意味着数组肯定也是一个Iterable,而任何自动包装也不会自动发生
public class ArrayIsNotIterable {
static <T> void test(Iterable<T> ib) {
for(T t : ib){
System.out.println(t + " ");
}
}
public static void main(String[] args) {
test(Arrays.asList(1, 2, 3));
String[] strings = {"A", "B", "C"};
// test(strings); 编译报错
test(Arrays.asList(strings));
}
}
适配器方法惯用法
如果现在又一个Iterable类,你想要添加一种或多种在foreach语句中使用这个类的方法,应该怎么做呢?例如,假设你希望可以选择以向前的方向或是向后的方向迭代一个单词列表。如果直接继承这个类,并覆盖iterator()方法,你只能替换现有的方法,而不能实现选择。
一种解决方案是所谓适配器方法的惯用法。“适配器”部分设计模式,因为你必须提供特定接口以满足foreach语句。当你有一个接口并需要另一个接口时,编写适配器就可以解决问题。
class ReversibleArrayList<T> extends ArrayList<T> {
public ReversibleArrayList(Collection<T> c) { super(c); }

public Iterable<T> reversed() {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
int current = size() - 1 ;
public boolean hasNext(){ return current > -1; }
public T next() { return get(current--); }
public void remove() {
throw new UnsupportedOperationException();
}
};

}
};
}

}

public class AdapterMethodIdiom {
public static void main(String[] args) {
ReversibleArrayList<String> ral = new ReversibleArrayList<>(Arrays.asList("To be or not to be".split(" ")));
for(String s : ral){
System.out.print(s + " ");
}
System.out.println();
for (String s : ral.reversed()) {
System.out.print(s + " ");
}
}
}

时间: 2024-11-06 16:51:33

持久对象(编程思想)的相关文章

27---面向对象编程思想

一 面向过程与面向对象 面向过程 ''' 面向过程: 核心:过程 过程的终极奥义就是将程序流程化 过程就是'流水线',用来分步骤解决问题 ''' 面向对象 ''' 面向对象: 核心:对象 对象的终极奥义就是将程序'整合' 对象是'容器':用来盛放数据与功能的 类也是'容器':该容器用来存放同类对象共有的数据与功能 ''' 二 面向对象---如何一步一步进行整合 整合引入---化妆盒 如果我们把"化妆"比喻为要执行的业务逻辑,此时只需要拿来一样东西即可,那就是彩妆盒,因为彩妆盒里整合了化

JAVA编程思想(1) - 一切都是对象

-"如果我们说另一种不用的语言,那么我们就会发觉一个有些不同的世界" 1. 用引用操纵对象 每种编程语言都有自己的数据处理方式.有些时候,程序员必须时刻留意准备处理的是什么类型.您曾利用一些特殊语法直接操作过对象,或处理过一些间接表示的对象吗(C或C++里的指针)? 所有的这一切在JAVA里都得到了简化.在JAVA里一切都被视为对象,尽管是一切都被看成对象,但操纵的标识符实际上是一个"引用"而已,简单来说是:对象好比"电视",我们拥有的引用是&q

Java编程思想 4th 第2章 一切都是对象

Java是基于C++的,但Java是一种更纯粹的面向对象程序设计语言,和C++不同的是,Java只支持面向对象编程,因此Java的编程风格也是纯OOP风格的,即一切都是类,所有事情在类对象中完成. 在Java中,使用引用来操纵对象,在Java编程思想的第四版中,使用的术语是"引用(reference)",之前有读过Java编程思想第三版,在第三版中,使用的术语是"句柄(handle)",事实上,我觉得第三版的术语"句柄"更加形象传神,就像你用一个

c++编程思想(一)--对象导言

回过头来看c++编程思想第一章,虽然只是对c++知识的一个总结,并没有实质性知识点,但是收获还是蛮多的! 下面感觉是让自己茅塞顿开的说法,虽然含义并不是很准确,但是很形象(自己的语言): 1.类描述了一组具有相同特性(数据元素)和相同行为(功能)的对象,本质就是一个数据类型,已存在的数据类型只是表示计算机的存储单位,定义新的类就是为了与问题结合,解决问题-----不要把类想的很复杂,直接抽象成这样 2.类要产生工作,会有一个接口,来实现功能 3.程序猿分为类创建者和客户程序猿(调用别人的类).客

1.JAVA 编程思想——对象入门

对象入门 欢迎转载,转载请标明出处:    http://blog.csdn.net/notbaron/article/details/51040219 如果学JAVA,没有读透<JAVA 编程思想>这本书,实在不好意思和别人说自己学过JAVA.鉴于此,蛤蟆忙里偷闲,偷偷翻看这本传说中的牛书. 面向对象编程OOP具有多方面吸引力.实现了更快和更廉价的开发与维护过程.对分析与设计人员,建模处理变得更加简单,能生成清晰.已于维护的设计方案. 这些描述看上去非常吸引人的,不过蛤蟆还是没啥印象(至少到

JAVA编程思想学习笔记——第一章 对象导论

搞了一年多java,野路子出身,发现java基础这块还是相当的薄弱!故决定学习<Java编程思想>这本书.在此把学习的知识点记录下! 面向对象的五大特性 1.万物皆为对象 2.程序是对象的集合,它们通过发送消息来告诉彼此所要做的 3.每个对象都由自己的由其它对象所构成的存储 4.每个对象都拥有其类型 5.某一特定类型的所有对象都可以接收同样的信息  单根继承结构 所有的类都继承自单一的基类,Object.在单根集成结构中的所有对象都具有一个公用接口,所以他们归根到底都是相同的基本类型.单根集成

【java编程思想--学习笔记(四)】对象导论

写这篇博客的前言: 长话短说,我希望通过阅读<java编程思想>来使我的代码 简洁可用 . 目的的层次不同,首先具体的目标是,了解Java的特性和巩固Java的基础. 更抽象的目的如下: 1.期待以巩固基础的方式,使代码优美,简洁,高效. 2.使自己写的模块能够开放适度,好用. 3.形成一种对代码是否优美的审美观. 于是<Java编程思想>第一章 对象导论 由此开始. 1.1 抽象过程 java 相对于命令式语言的优势在于只针对于待解问题建模.后者所做的主要抽象要求所做问题基于计算

Java编程思想(一)——一切都是对象

<Java编程思想> 作者:Bruce Eckel 虽然这本书是经典,但是对于一个入门java,又没有其他编程经验的人来讲,实在难以看懂,前前后后看了三遍. 第一次什么都不懂的时候硬着头皮看,没看完,看了前面忘了后面,中间很多看不懂.第二次的时候,看懂了很多,但是不知道经典在何处. 第三次,是自己用了这门语言一年后,知道所谓的经典是什么,java的特性都在这里,这书不是从基础的JDK怎么装开始讲起.,大部头的一本书,现代人的话很少去翻了,其实可以当参考书,看哪一部分忘了,直接温故即可.一次在学

『Java编程思想-第四版』第二章:一切都是对象

Java编程思想-第四版学习总结,此为第二章:一切都是对象. package com.w3cjava.second; @SuppressWarnings("all") public class Second { /** * Java编程思想(第四版) * 第2章 一切都是对象 * @param args */ public static void main(String[] args) { /** * 2.1 用引用操作对象 * 遥控器(引用)操作电视机(对象),改变音量,改变频道 *

【Java编程思想】二、一切都是对象

尽管Java是基于C++的,但是相比之下,Java是一种更“纯粹”的面向对象设计语言. 2.1 用引用操纵对象 一切都被视为对象, 因此可采用单一固定的语法.尽管一切都被看作对象,但操纵的标识符实际上是对象的一个“引用”. Java里的“引用”与C++中的“引用”是有区别的,但是这个概念不需要完全明白,学会处理引用就可以了. 2.2 必须由你创建所有对象 new关键字的意思就是“给我一个新对象”! 2.2.1对象存储到什么地方 1)寄存器 2)堆栈(RAM) 3)堆(RAM) 4)常量存储(RO