笔记_from_Java编程思想(第十一章 持有对象)

基本概念

Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
1) Collection。一个独立元素的序列,这些元素都服从一条或多条规则:
List必须按照插入的顺序保存元素
Set不能有重复元素
Queue按照排队规则来确定对象产生的顺序
2) Map。一组成对的“键对值”对象,允许使用键来查找值。ArrayList允许使用数字来查找。
所有Collection都可以用foreeach语句遍历。

添加一组元素

Array.asList()方法接受一个数组或是一个用逗号分隔的元素列表(使用可变参数)并将其转换为一个List对象。Collection.addAll()方法是接受一个Collection对象,以及一个数组或一个用逗号分隔的列表,将元素添加到Collection中。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class test
{
    public static void main(String[] args) {
        Collection<Integer> collection= new ArrayList<>(Arrays.asList(1,2,3,4,5));
        Integer[] moreInts={6,7,8,9,10};
        collection.addAll(Arrays.asList(moreInts));

        Collections.addAll(collection,11,12,13,14,15);
        Collections.addAll(collection, moreInts);
        List<Integer> list=Arrays.asList(16,17,18,20);
        list.set(1, 99);

        System.out.println("collection:");
        for(Integer temp:collection)    System.out.print(temp+" ");
        System.out.println();
        System.out.println("list:");
        for(Integer temp:list)  System.out.print(temp+" ");
    }
}
/*输出结果:
    collection:
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 6 7 8 9 10 
    list:
    16 99 18 20
*/

容器的打印

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.List;
import java.util.ArrayList;
public class test
{
    static Collection fill(Collection<String> collection)
    {
        collection.add("rat");  collection.add("cat");
        collection.add("dog");  collection.add("dog");
        return collection;
    }
    static Map fill(Map<String,String> map)
    {
        map.put("rat", "Fuzzy");    //Map.put(key,value)的方法能够增加值
        map.put("cat","Rags");
        map.put("dog","Bosco");
        map.put("dag","spot");
        return map;
    }
    public static void main(String[] args) {
        System.out.println(fill(new ArrayList<String>()));     //ArrayList和LinkedList都是List类型
        System.out.println(fill(new LinkedList<String>()));
        System.out.println(fill(new HashSet<String>()));       //HashSet、TreeSet和LinkedHashSet都是Set类型,每个相同的像只能存在一次
        System.out.println(fill(new TreeSet<String>()));
        System.out.println(fill(new LinkedHashSet<String>()));
        System.out.println(fill(new HashMap<String,String>()));
        System.out.println(fill(new TreeMap<String,String>()));
        System.out.println(fill(new LinkedHashMap<String,String>()));
    }
}
/*
//输出结果:
[rat, cat, dog, dog]
[rat, cat, dog, dog]
[rat, cat, dog]
[cat, dog, rat]
[rat, cat, dog]
{rat=Fuzzy, cat=Rags, dag=spot, dog=Bosco}
{cat=Rags, dag=spot, dog=Bosco, rat=Fuzzy}
{rat=Fuzzy, cat=Rags, dog=Bosco, dag=spot}
*/

List

两种基本的List
ArrayList:用于随机访问元素,但是在List的中间插入和移除元素时较慢。
LinkedList:通过代价较低的在List中间进行插入和删除操作,提供优化的顺序访问
List的主要方法们:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class test
{
    public static void main(String[] args) {
        Integer[] n={1,2,3,4,5,6,7};
        //List<Integer> Num=Arrays.asList(n);       //此方法返回的list没有add()和remove()方法
        Collection<Integer> collection= new ArrayList<>(Arrays.asList(n));
        List<Integer> Num= new ArrayList<Integer>();
        Num.addAll(collection);
        System.out.println("1.原始:"+Num);
        Integer In= 10;
        Num.add(In);
        System.out.println("2.使用add(In):"+Num);
        Num.remove(In);
        System.out.println("3.使用remove(In):"+Num);     //用数字X作参数为移去排在第X个元素 e.g Num.remove(5) 
                                                        //输出应为:3.使用remove():[1, 2, 3, 4, 5, 7, 10]
        In=Num.get(1);
        System.out.println("4.使用get(1)得到的:"+In+" 使用indexOf(In)得到的:"+Num.indexOf(In));
        List<Integer>sub= Num.subList(0, 4);            //从0开始计
        System.out.println("5.使用subList(0,4)得到的sub:"+sub);
        System.out.println("6.1使用contains(In):"+Num.contains(In));   //一个放类,一个放容器
        System.out.println("6.2使用containsAll(sub):"+Num.containsAll(sub));
        List<Integer> Copy= new  ArrayList<Integer>(Num);
        Copy.retainAll(sub);
        System.out.println("7.使用retainAll(sub):"+Copy);
        Copy= new ArrayList<Integer>(Num);
        Copy.removeAll(sub);
        System.out.println("8.使用removeAll(sub):"+Copy);
        Copy.addAll(0,sub);
        System.out.println("9.使用addAll(sub):"+Copy);
        System.out.println("10.使用isEmpty():"+Copy.isEmpty());
        Object[] o=Num.toArray();
        System.out.println("11.使用toArray():"+o+" o[2]:"+o[2]);
    }
}

迭代器

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class test
{
    public static void main(String[] args) {
        List<Integer> Num= new ArrayList<Integer>();
        
        for(int i=-10;i<=10;i++)   Num.add(i);  //添加元素应在创建迭代器之前
        Iterator<Integer> it= Num.iterator();
        //使用next()获得序列中的下一个元素
        System.out.println(it.next());  //第一个元素
        //使用remove()将迭代器新近返回的元素删除
        it.remove();    //移除第一个元素
        Integer temp=0;
        //使用hasNext()检查序列中是否还有元素
        while(it.hasNext())
        {
            if(temp>it.next())  it.remove();
        }
        System.out.println();
        for(Integer i:Num)      //foreach语句也可以实现迭代
            System.out.print(i+" ");
    }
}

ListIterator

ListIterator是一个更加强大的Iterator类型,它只能用于各种List类的访问。Iterator只能向前移动,而ListIterator可双向移动

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class test
{
    public static void main(String[] args) {
        List<Integer> Num= new ArrayList<Integer>();
        for(int i=0;i<=10;i++)   Num.add(i*2);  //添加元素应在创建迭代器之前
        ListIterator<Integer> it=Num.listIterator();
        while(it.hasNext())
        {
           System.out.print(" Index: "+it.nextIndex()+" :"+it.next());
        }
        System.out.println();
        while(it.hasPrevious())
        {
            System.out.print(" Index: "+it.previousIndex()+" :"+it.previous());
        }
    }
}
/*输出:
 Index: 0 :0 Index: 1 :2 Index: 2 :4 Index: 3 :6 Index: 4 :8 Index: 5 :10 Index: 6 :12 Index: 7 :14 Index: 8 :16 Index: 9 :18 Index: 10 :20
 Index: 10 :20 Index: 9 :18 Index: 8 :16 Index: 7 :14 Index: 6 :12 Index: 5 :10 Index: 4 :8 Index: 3 :6 Index: 2 :4 Index: 1 :2 Index: 0 :0
*/

LinkedList

import java.util.LinkedList;

public class test
{
    public static void main(String[] args) {
        LinkedList<Integer> Num= new LinkedList<Integer>();
        for(int i=0;i<=10;i++)   Num.add(i*2);  //添加元素应在创建迭代器之前
        //ListIterator<Integer> it=Num.listIterator();
        System.out.println("0.初始:"+Num);
        System.out.println("1.getFirst():"+Num.getFirst());    //得到队列首个元素
        System.out.println("2.element():"+Num.element());
        System.out.println("3.peek():"+Num.peek());
        System.out.println("4.remove():"+Num.remove());
        System.out.println("5.使用remove()的getFirst():"+Num.getFirst());
        System.out.println("6.removeFirst():"+Num.removeFirst());  //移去第一个,但remove()方法缺省时,默认移去第一个
        System.out.println("7.当前的Num:"+Num);
        System.out.println("8.poll():"+Num.poll());
        Num.addFirst(12);
        Num.addLast(120);
        System.out.println("9.addFirst(12)和addLast(120)后:"+Num);
        System.out.println("10.offer(200)后:"+Num.offer(200)+" "+Num); //返回boole类型,在尾部插入
    }
}
/*
//输出:
0.初始:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
1.getFirst():0
2.element():0
3.peek():0
4.remove():0
5.使用remove()的getFirst():2
6.removeFirst():2
7.当前的Num:[4, 6, 8, 10, 12, 14, 16, 18, 20]
8.poll():4
9.addFirst(12)和addLast(120)后:[12, 6, 8, 10, 12, 14, 16, 18, 20, 120]
10.offer(200)后:true [12, 6, 8, 10, 12, 14, 16, 18, 20, 120, 200]
*/

Stack

“栈“通常是”后进先出“。LinkedList具有能够直接实现栈的所有功能的方法,因此可以直接将LikedList作为栈使用

import java.util.Stack;

public class test
{
    public static void main(String[] args) {
       Stack<Integer> Num= new Stack<>();
       for(int i=0;i<=10;i++)   Num.push(i*2);
       System.out.println("1.初始:"+Num);
       //注意:peek()返回栈顶元素,pop()返回栈顶元素且将其删去
       System.out.println("2.peek():"+Num.peek());
       System.out.println("3.使用peek()后:"+Num);
       System.out.println("4.pop():"+Num.pop());
       System.out.println("5.使用pop()后:"+Num);
    }
}
/*
输出:
1.初始:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
2.peek():20
3.使用peek()后:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
4.pop():20
5.使用pop()后:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
*/

Set

Set不保存重复的元素,常用于测试归属性,正因如此,查找是Set中最常用的操作,因此我们通常选择HashSet的实现,它专门对快速查找进行了优化。
Set具有与Collection完全一样的接口,因此没有额外的功能。

import java.util.HashSet;
import java.util.Random;
import java.util.LinkedHashSet;
import java.util.Set;
public class test
{
    public static void main(String[] args) {
        Set<Integer> set= new HashSet<>();
        Set<Integer> set2= new LinkedHashSet<>();
        Random rand= new Random(100);
        //重复输入相同的随机数
        for(int i=0;i<100;i++)
        {
            int temp=rand.nextInt(20);
            set.add(temp);
            set2.add(temp);
        }
        System.out.println(set);
        System.out.println(set2);
    }
}
/*
输出:
[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[15, 10, 14, 8, 11, 6, 16, 3, 13, 2, 17, 12, 19, 0, 18, 5, 7, 4, 9]
*/
//原文中得到的结果是无序的,而现在得到的结果显然是有序,因此猜测原意指LinkedHashSet


HashSet的存储结构使用散列函数;TreeSet将元素存储在红-黑树数据结构中;LinkedHashSet也是使用散列,但使用了链表来维护元素的插入顺序。
可以使用contains()方法确认Set中某元素的归属性。

Map

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class test
{
    public static void main(String[] args) {
        Random rand= new Random(100);
        Map<Integer,Integer> map= new HashMap<Integer,Integer>();
        for(int i=0;i<1000;i++)
        {
            int r=rand.nextInt(20);
            Integer freq=map.get(r);
            map.put(r,freq==null?1:freq+1);
        }
        System.out.print(map);
    }
}
/*
输出:
{0=65, 1=35, 2=48, 3=44, 4=40, 5=48, 6=43, 7=46, 8=64, 9=49, 10=44, 11=60, 12=48, 13=61, 14=52, 15=51, 16=56, 17=49, 18=44, 19=53}
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
*/

在main()中,自动包装机制将随机生成的int转换为HashMap可使用的integer引用(不能使用基本类型的容奇)。如果键不在容器中,get()方法将会返回null(这表示该数字第一次被找到,否则get()方法将会产生于该键相关联的Integer值,之后该值递增,自动包装机制再次被调用)
此外,Map与数组和其他的Collection一样,很容易被扩展到多维。E.g 你正在跟踪一个拥有多个宠物的人 Map<Person,List>
Map也可以返回键值的集合,keySet()。

Queue

队列是一个典型的先进先出容器。LinkedList提供了方法以支持队列,并且实现了Queue的接口,因此LinkedList可以用作Queue的实现。通过LinkedList向上转型为Queue:

import java.util.Queue;
import java.util.Random;
import java.util.LinkedList;
public class test
{
    public static void main(String[] args) {
        Queue<Integer> queue= new LinkedList<Integer>();
        Random rand= new Random(46);
        for(int i=0;i<15;i++)   queue.offer(rand.nextInt(1000));    //offer()方法将一个元素插入队尾
        System.out.println(queue);
        //peek()和element()都将在不移除的情况下返回队头
        //当队列为空时,peek()返回null,element()抛出NoSuchElementException类异常
        System.out.println("peek():"+queue.peek()+" element():"+queue.element());
        System.out.println(queue);
        //两者都为移除并返回队头
        //当队列为空,poll()返回null,remove()抛出NoSuchElementException类异常
        System.out.println("poll():"+queue.poll()+" remove():"+queue.remove());
        System.out.println(queue);
    }
}
/*
输出:
[633, 267, 875, 995, 222, 578, 925, 3, 262, 314, 797, 684, 355, 589, 342]
peek():633 element():633
[633, 267, 875, 995, 222, 578, 925, 3, 262, 314, 797, 684, 355, 589, 342]
poll():633 remove():267
[875, 995, 222, 578, 925, 3, 262, 314, 797, 684, 355, 589, 342]
*/

PoriorityQueue

import java.util.PriorityQueue;
import java.util.Random;
public class test
{
    public static void main(String[] args) {
        PriorityQueue<Integer> queue= new PriorityQueue<Integer>(); //注意:LinkedList不能向上转型!
        Random rand= new Random(46);
        for(int i=0;i<15;i++)   queue.offer(rand.nextInt(1000));    //offer()方法插入元素后将自动排序
        System.out.println(queue);
        System.out.println("peek():"+queue.peek()+" element():"+queue.element());
        System.out.println(queue);
        //返回的都是优先级最高的
        //两者都为移除并返回队头
        //当队列为空,poll()返回null,remove()抛出NoSuchElementException类异常
        System.out.println("poll():"+queue.poll()+" remove():"+queue.remove());
        System.out.println(queue);
    }
}
/*
输出:
[3, 222, 342, 262, 314, 578, 355, 995, 267, 633, 797, 875, 684, 925, 589]
peek():3 element():3
[3, 222, 342, 262, 314, 578, 355, 995, 267, 633, 797, 875, 684, 925, 589]
poll():3 remove():222
[262, 267, 342, 589, 314, 578, 355, 995, 925, 633, 797, 875, 684]
*/

Foreach和迭代器

Foreach语法主要用于数组,但是它也可以应用于任何Collection对象。JavaSE5引进了新的被称为Iterable接口被foreach用来在序列中移动,因此任何Iterable的类都可用于foreach语句中。Foreach语句用于数组和任意的Iterable类,但不意味着数组也是Iterable,如果将数组当作一个Iterable参数,传递将失败。

总结

Java提供了大量持有对象方式
1) 数组将数字和对象相关联,可以保存基本类型数据,但数组一旦生成,容量不能改变。
2) Collection保存单一的元素,而Map保存相关联的键值对。各种Collection和Map都可以在加入新元素时自动调整尺寸。容器不能持有基本类型,但自动包装机制会执行基本类型到容器中所持有的包装类型之间的转换。
3) List与数组一样,建立了数字索引,但List可以自动扩容。
4) 大量随机访问选ArrayList,如果要频繁插入、删除元素选LinkedList。
5) ListedList支持栈和队列。
6) HashMap用于快速访问;TreeMap保持按“键“排序;LinkedMap保持元素插入的顺序。
7) Set不接受重复元素;HashSet提供快速查询;TreeSet保持元素处于排序;LinkedHashSet以插入顺序保存元素
8) 少用过时的Vector、HashTable、Stack



总结

[1] Bruce Eckel.Java编程思想[M].陈昊鹏,北京:机械工业出版社出版社.2007

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值