首页 > 代码库 > Java编程思想(八) —— 持有对象(1)

Java编程思想(八) —— 持有对象(1)

书中的原标题是——holding your object,把握你的对象,译者翻译成持有对象。这是用的最多的类之一。


作者说的,如果一个程序包含固定数量的且其生命周期都是已知的对象,那么这是一个非常简单的程序。确实,如果数组大小已知,那么就很简单了。


除了数组,Java提供了容器类来holding object。


1)泛型和类型安全的容器

ArrayList,可以自动扩充大小的数组,add插入对象,get访问对象,size查看对象数目。

class Apple{}

public class Box {
    public static void main(String[] args) {
        ArrayList<Apple> a = new ArrayList<Apple>();
        a.add(new Apple());
    }
}

泛型(就是跟在ArrayList后面的那个尖括号指明Apple类型的标识)的添加可以在编译期间防止将错误类型的对象放进容器中。

同样,容器也可以用foreach语法。


2)概念

容器类作用是保存对象。分为两个:

一、Collection,List顺序保存元素,Set不能有重复元素,Queue按照排队来。

二、Map,键值对,通过键找值或者被称为字典。


对了,写了这么多篇,忘记说一件重要的事情了,懂得查API文档,最好看英文版。Collection是什么,类还是接口,一查就知道了。

public interface List<E>
extends Collection<E>


public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable

这样的关系就出来了。


3)添加一组元素

public class AddGroup {
    public static void main(String[] args) {
        Collection<Integer> c = new ArrayList<Integer>(Arrays.asList(1,2,3,4));
        Integer[] group = {5,6,7,8 };
        c.addAll(Arrays.asList(group));
        System.out.println(c);
        Collections.addAll(c, 9,0);
        System.out.println(c);
    }
}

//[1, 2, 3, 4, 5, 6, 7, 8]
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

Collections.addAll,Adds all of the specified elements to the specified collection.

将其他元素添加到Collection c中,而Collection.addAll是添加一组元素。


4)容器的打印

其实上面的代码已经看出,具体的容器已经实现了自己的toString方法。


5)List

List有两种:ArrayList,随机访问元素快,中间插入和删除操作慢。

                     LinkedList,随机访问慢,但是中间插入和删除快,类似链表。


List常用方法:

class Member{
    int age;
    Member(int i){
        age = i;
    }
    public String toString(){
        return "member"+age;
    }
}

public class ListMethod {
    public static void main(String[] args) {
        List<Member> members = new ArrayList<Member>();
        Member member1 = new Member(1);
        
        //添加元素
        members.add(member1);
        
        //判断容器是否为空
        System.out.println(members.isEmpty());
        
        //判断容器是否包含该元素
        System.out.println(members.contains(member1));
        
        //显示索引
        System.out.println(members.indexOf(member1));
        
        //移除元素
        members.remove(member1);
        System.out.println(members);
        
        Member member2 = new Member(2);
        Member member3 = new Member(3);
        Member member4 = new Member(4);
        members.add(member2);
        members.add(member3);
        members.add(member4);
        
        //类似subString,从索引0开始截取到1,包含0和1
        System.out.println(members.subList(0, 2));
        
        //移除 不同于remove
        //removeAll(Collection<?> c) 
        //remove(int index)   remove(Object o) 
        members.removeAll(members);
        System.out.println(members);
    }
    
}

6)迭代器

在没用迭代器之前,遍历是这样写的:

        for(int i = 0; i < newList.size(); i++){
            System.out.println(newList.get(i));
        }

而迭代器被称为轻量级对象,创建的代价小。

        Iterator<Member> iterator = members.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

next移动下一个元素,但是拿到的当前元素。hasNext检查是否还有元素,Iteratorf容器返回一个Iterator。


7)ListIterator

这个之前没听过,Iterator只能向前移动,ListIterator可以双向移动。

        ListIterator<Member> iterator = members.listIterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        
        while(iterator.hasPrevious()){
            System.out.println(iterator.previous());
        }

向前输出,向后输出。


8)LinkedList

插入移除高效。

方法很容易理解,属于自解释型的方法名。

public class TestLinkedList {
    public static void main(String[] args) {
        LinkedList<Member> members = new LinkedList<Member>();
        Member member1 = new Member(1);
        Member member2 = new Member(2);
        Member member3 = new Member(3);
        members.add(member1);
        members.add(member2);
        members.add(member3);
        
        //返回列表头
        System.out.println(members.peek());
        
        //移除并返回列表头
        System.out.println(members.removeFirst());
        System.out.println(members);
        
        //返回并移除表头
        System.out.println(members.poll());
        System.out.println(members);
        
        //removelast 移除最后一个
        members.add(member1);
        members.add(member2);
        System.out.println(members.removeLast());
        System.out.println(members);
        
        
        //addLast和add一样 都是往列表尾插入元素 addFirst自然就是表头
        members.add(member2);
        members.addFirst(member2);
        members.addLast(member2);
        System.out.println(members);
    }
}

9)Stack

栈,后进先出,

其实用LinkedList就可以实现栈的功能了,push,进的时候,只需要addFirst,pop,出的时候,只需要removeFirst,这样就达到了先进后出


10)Set

Set,元素不重复。

Set与Collection有完全一样的接口,但是不同List,虽然Set就是Collection,但是行为不同,这就是多态和继承的应用了。

public class TestSet {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<Integer>();
        Random r = new Random(400);
        
        for(int i = 0;i<20;i++){
            set.add(r.nextInt(300));
        }
        System.out.println(set);
    }
}

HashSet,没有重复元素,顺序也无规律,其实是使用了散列,以后会提到。


如果:

  Set<Integer> set = new TreeSet<Integer>();
会发现是有序的,TreeSet将元素存储在了红黑树里面。

书中有一处错误:LinkedHashSet写成LinkedHashList了,它也使用散列,但是看起来使用了链表维护元素插入顺序。


持有对象这一章的内容不会难,因为平时用的太多,就是内容多,接下来下一篇会写Map,Queue和总结这一章的东西。



------------------------- 独在异乡为异客,每逢中秋倍思亲-----------------------------






Java编程思想(八) —— 持有对象(1)