zoukankan      html  css  js  c++  java
  • Java编程思想:第11章 持有对象

    Java容器框架提供了多种不同特性的容器方便我们管理任意数量的对象。

    11.1泛型和类型安全的容器

    JavaSE5之前的容器允许我们向其中放入不同类型的对象,但是取出的时候需要进行类型强制转换,很容易出现问题。有了泛型之后需要我们只能向集合里添加指定类型及其子类,取出时也不需要类型转换,这个功能是编译器完成的。

    11.2基本概念

    Java中容器分为2个概念:

    1)Collection:一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入顺序保存元素,Set不能有重复元素。Queue按照排队规则确定对象产生的顺序(通常与插入顺序相同)。

    2)Map:映射表允许我们使用另一个对象来查找某个对象,它也被称为关联数组。

    理想情况下在创建对象时向上转型成接口,方便切换实现,除非需要用到特有方法。

    11.3添加一组元素

    java.util包里Arrays和Collections类有很多实用方法,可以在一个Collection里添加一组元素。

    Arrays.asList()接受一个数组或者可变长参数,转换成一个固定长度(不能add)的list。

    Collections.addAll()接受一个Collection对象和一个可变长参数,向Collection里添加一组元素。

    Collection.addAll()只能接收一个Collection对象,没有上面灵活。

    首选:Collections.addAll()

    注意Arrays.asList()对产生的List类型做了最理想的假设:即最近公共父类,这可能会产生问题。

    比如:父类Person,一级子类Man,二级子类WhiteMan、BlackMan

    List<Person> list = Arrays.asList(new WhiteMan(),new BlackMan());

    这时会编译出错,因为编译器找到理想的类型是List<Man>而不是List<Person>,我们需要手动指定asList类型:

    List<Person> list = Arrays.<Person>asList(new WhiteMan(),new BlackMan());

    使用Collections.addAll()不需要指定类型,因为第一个参数里已经有类型了。

    11.4容器的打印

    容器类不需要做特殊处理即可直接打印,并且可以生成格式很好的输出。

    11.5List

    List可以把元素维护在特定的序列里,在Collection基础上添加了很多操作index的方法,如获取,设置,插入,删除。contains()/remove()/indexOf()等行为是根据equals()结果来的。

    ArrayList提供高效访问,低效插入删除。LinkedList相反,一般情况使用ArrayList除非进行大量插入删除使用ArrayList影响性能了才改用LinkedList。

    subList()可以返回大List里的一个子List,相当于对象引用copy了一份,所以list.containsAll(subList)是true,对subList元素的操作也会影响原来的list。

    retainAll()交集操作,保留两个list里的共同元素,基于equals()。

    其他方法...

    11.6迭代器

    任何容器都必须有某种方式可以插入元素并把它取回。对于List可以用get取出,如果从更高层次思考,会发现要使用容器,必须对容器的确切类型编程。如果我们可以使得对List使用的代码也可以对Set使用,就会非常方便。迭代器Iterator就是用于这种目的,使得我们不需要关心序列的底层结构就可以使用next()、hasNext()、remove()来遍历或删除序列中的元素。如果只是遍历不需要修改List,使用foreach更加方便。

    remove()用了删除最后一次next()得到的元素,所以必须先使用next()取得元素,然后才能remove()

    11.6.1ListIterator

    是一个更加强大的Iterator子类型,但只能用于List类型的访问。允许进行双向(前后)访问,可以使用set替换被访问的最后一个元素,可以用listIterator(n)重载方法创建一个一开始就指向索引为n的ListIterator.

    11.7LinkedList

    LinkedList相比ArrayList除了某些操作性能不同之外,还添加了可以使其用作栈,队列或双端队列的方法。很多方法名称不同但是作用差不多,主要用于在不同上下文环境下使用。如element() getFirst(),remove(),removeFirst(),peek(),pop()等。

    11.8Stack

    后进先出,就像弹夹一样的储存装置。LinkedList有实现栈功能的所有方法,可以直接作为栈使用,但是有时候用一个真正的栈更可以把问题解决清楚优雅。

    Java中提供了java.util.Stack类用于模拟一个Stack,但是设计的并不恰当:

    1)Stack从Vector继承而来,多了很多不必要的方法,而且有的方法会破坏Stack的规则:如add(index,obj)

    2)Vector是数组实现的,在push()pop()时候效率很低,应该使用链式结构

    我们可以自己写一个:

    public class Stack<T>{

      private LinkedList<T> list = new LinkedList<>();

      public void push(T t){list.addFirst(t);}

      public T peek(){return list.getFirst();}

      public T pop(){return list.removeFirst();}

      public boolean empty(){return list.isEmpty();}

      public String toString(){return list.toString();}

    }

    11.9Set

    Set不保存重复的元素,最常用的功能就是测试是否包含对象,因此查找就成为了Set中最重要的操作,HashSet实现专门对快速查找进行了优化。

    Set与Collection接口完全一致,只是行为不同(多态的特性)。Set是根据对象的值来决定归属性的。

    11.10Map

    把对象映射到其它对象的能力是解决很多问题的杀手锏。

    遍历时可以返回键的set或者键值对的set

    11.11Queue

    队列是典型的先进先出FIFO容器,取出顺序与放入顺序一致。是一种可靠的把对象从程序的某个区域传输到另一个区域的途径。在并发编程中特别重要。

    LinkedList提供了方法可以支持队列行为,并且也实现了Queue接口,所以它可以用作Queue的一种实现。

    Queue<Integer> q = new LinkedList<>();

    offer():插入队尾或返回false

    peek()/element()返回队头,队列为空时peek返回null,element抛出NoSuchElementException

    poll()/remove()返回队头并移除,队列为空时pool返回null,remove抛出NoSuchElementException

    11.11.1PriorityQueue

    队列规则:给定一组队列元素,确定下一个弹出元素的规则。先进先出是典型的一种队列规则。

    优先级队列声明下一个弹出元素是优先级最高的元素。PriorityQueue在JavaSE5开始出现,默认元素顺序是按照自然顺序弹出,可以设置一个Comparator来控制这种优先级。

    11.12Collection和Iterator

    实现Collection接口就必须提供创建Iterator的方法,保证了通用能力。

    11.13ForEach与迭代器

    任何实现了Iterable接口的类,都可以在foreach中使用。数组和Collection类都可以使用。但Map不行。

    11.13.1适配器方法惯用法

    使用不同的方法产生不同的Iterator,用于不同的迭代方式。

    11.14总结

    Java提供了大量持有对象的方式:

    1.数组,保存单一类型对象,可以是多维的,可以保存基本类型,但是容量不可变。

    2.Collection保存单一元素,Map保存键值对。有了泛型不需要进行类型转换,不可持有基本类型但是会自动包装来处理,容量可变。

    3.List也建立了数字和对象的关联,所以数组和List都是排序好的容器。List能自动扩容

    4.大量随机访问用ArrayList,经常中间插入删除用LinkedList。

    5.队列以及堆栈行为用LinkedList完成。

    6.Map是一种将对象与对象相关联的设计。HashMap用于快速访问,TreeMap保持键始终处于排序状态,没有HashMap快。LinkedHashMap保持元素插入顺序,但是也通过散列提供了快速访问的能力。

    7.Set不接受重复元素。HashSet提供最快查询速度,TreeSet保持元素处于排序状态,LinkedHashSet以插入顺序保存元素,查询也快。

    8.不应该使用过时的Vector(同步效率慢,扩容时候翻倍ArrayList扩一半),HashTable(同步效率慢),Stack

    集合框架图:

  • 相关阅读:
    指向指针的指针
    判断是否遵守某个协议
    oc继承,实现,分类
    oc中没有空指针错误
    oc方法
    指针
    Array.diff
    ATM机允许4位或6位密码,而密码只能包含4位或6位数字。 如果函数传递了一个有效的PIN字符串,返回true,否则返回false。
    替换字符串中的字符为“(” 或“)”
    python 异常处理
  • 原文地址:https://www.cnblogs.com/superzhao/p/4820041.html
Copyright © 2011-2022 走看看