Skip to content

Latest commit

 

History

History
379 lines (328 loc) · 12.2 KB

集合类.md

File metadata and controls

379 lines (328 loc) · 12.2 KB

集合类

数组的对象赋值和初始化
//:ArraySize.java
//Initialzation & re-assignment of arrays
package c08;

class Weeble{}//A small mythical creature

public class ArraySize{
    public static void main(String[] args){
        //Arrays of objects;
        Weeble[] a;//Null handle
        Weeble[] b=new Weeble[5];//Null handle
        Weeble[] c=new Weeble[4];
        for(int i=0;i<c.length;i++){
            c[i]=new Weeble();
        }
        Weeble[] d={new Weeble(),new Weeble(),new Weeble()};
        //Compile error
        //System.out.println("a.length="+a.length);
        System.out.println("b.length="+b.length);
        //The handle inside the array are automatically initialized to null;
        for(int i=0;i<b.length;i++){
            System.out.println("b["+i+"]="+b[i]);
        }
        System.out.println("c.length="+c.length);
        System.out.println("d.length="+d.length);
        a=d;
        System.out.println("a.length="+a.length);
        a=new Weeble[]{
            new Weeble(),new Weeble()
        };
        System.out.println("a.length="+a.length);
        
        //Arrays of primitives
        int[] e;//Null handle
        int[] f=new int[5];
        int[] g=new int[4];
        for(int i=0;i<g.length;i++){
            g[i]=i*i;
        }
        int[] h={11,47,93};
        //Compile error
        //System.out.println("e.length="+e.length);
        System.out.println("f.length="+f.length);
        for(int i=0;i<f.length;i++){
            System.out.println("f["+i+"]="+f[i]);
        }
        System.out.println("g.length="+g.length);
        System.out.println("h.length="+h.length);
        e=h;
        System.out.println("e.length="+e.length);
        e=new int[] {1,2};
        System.out.println("e.length="+e.length);
    }
}
动态集合初始化

可以在任何地方创建和初始化一个数组对象。

例如,假设hide()方法用于取得一个Weeble 对象数组,那么调用它时传统的方法是:

hide(d); 但在Java 1.1 中,亦可动态创建想作为参数传递的数组,如下所示: hide(new Weeble[] {new Weeble(), new Weeble() });

集合类只能容纳对象句柄。但对一个数组,却既可令其直接容纳基本类型的数据,亦可容纳指向对象的句 柄。利用Integer、Double 之类的“封装器”类,可将基本数据类型的值置入一个集合里。但正如本章后 面会在WordCount.java 例子中讲到的那样,用于基本数据类型的封装器类只是在某些场合下才能发挥作用。 无论将基本类型的数据置入数组,还是将其封装进入位于集合的一个类内,都涉及到执行效率的问题。显 然,若能创建和访问一个基本数据类型数组,那么比起访问一个封装数据的集合,前者的效率会高出许多。 当然,假如准备一种基本数据类型,同时又想要集合的灵活性(在需要的时候可自动扩展,腾出更多的空 间),就不宜使用数组,必须使用由封装的数据构成的一个集合。大家或许认为针对每种基本数据类型,都 应有一种特殊类型的Vector。但Java 并未提供这一特性。某些形式的建模机制或许会在某一天帮助Java 更 好地解决这个问题。

//retry的用法
/*
-----------------------
注释1,输出 0 1 2 3 4 
注释2,输出 0 1 2 3 4 6 7 8 9
相当与一个标识符,break,continue,跳到该标识符处
retry在循环外,break retry;//跳出循环(continue retry;效果一样,跳出循环)
retry在循环内,break retry;//结束此次循环,继续下次循环
*/

//testRequest.java
//测试跳出循环以及结束循环
public void testRequest() {
//        retry:// 1(行2)
        for (int i = 0; i < 10; i++) {
            retry:// 2(行4)
            while (i == 5) {
                continue retry;
            }
            System.out.print(i + " ");
        }
    }

//RetryTest.java
//循环嵌套测试
/*
-------------------------
retry相当于一个标记,只用在循环里面,很像goto语句,break到retry字符处。如果retry没有在循环(for,while)里面,在执行到retry时,就会跳出整个循环。如果retry在循环里面,可以理解为跳到了关键字处执行,不管几层循环。continue理解也是一样。
-------------------------
*/
//注释1,输出i=1;j=1;j=2;
//注释2,输出i=1;j=1;j=2;i=2;j=1;j=2;......i=1024;j=1;j=2;......一直打印下去
 public void RetryTest() {
        int i = 0;
        retry:  //1
        while (true) {
            i++;
            System.out.println("i=" + i);
            int j = 0;
//            retry:   //2
            for (; ; ) {
                j++;
                System.out.println("j=" + j);
                if (j == 2) {
                    break retry;
                }
            }
        }
    }

/*
----------------------------
retry就是一个标记,标记程序跳出循环的时候从哪里开始执行,功能类似于goto。
retry一般情况下:一是常常跟随for循环或while循环出现;
二就是常常跟随continue或是break,其中 break retry;用来表示退出retry循环,继续走循环下面的代码;而continue retry;则表示回到retry代码处,从循环体头开始执行。
retry的命名不是固定,只要符合Java的命名规范即可。例如retry1, retry2等等这样的名称都是合法的
----------------------------
*/
数组的返回
//:IceCream.java
//Returning arrays from methods

public class IceCream{
    static String[] flav={
        "Chocolate","Strawberry","Vanilla Fudge Swirl","Mint chip","Mocha Almond Fudge","Rum Raisin","Praline Cream","Mud Pie"
    };
    static String[] flavorSet(int n){
        //Force it to positive & within bounds:
        n=Math.abs(n)%(flav.length+1);
        String[] results=new String[n];
        int[] picks=new int[n];
        for(int i=0;i<picks.length;i++){
            picks[i]=-1;
        }
        for(int i=0;i<picks.length;i++){
            retry:
            while(true){
                int t=(int)(Math.random()*flav.length);
                for(int j=0;j<i;j++){
                    if(picks[j]==t) continue retry;
                }
                picks[i]=t;
                results[i]=flav[t];
                break;
            }
        }
        return results;
    }
    public static void main(String[] args){
        for(int i=0;i<20;i++){
            System.out.println("flavorSet("+i+")=");
            String[] f1=flavorSet(flav.le);
            for(int j=0;j<f1.length;j++)
                System.out.println("\t"+f1[j]);
        }
    }
}

数据库原子性:

原子性(Atomic):一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。实现事务的原子性,要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。

原子操作

原子操作:"原子操作(atomic operation)是不需要synchronized",这是多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切 换到另一个线程)。

//:CatsAndDogs.java
//Simple collection example(Vector)
import java.util.*;

class Cat{
    private int catNumber;
    Cat(int i){
        catNumber=i;
    }
    void print(){
        System.out.println("Cat #"+catNumber);
    }
}

class Dog{
    private int dogNumber;
    Dog(int i){
        dogNumber=i;
    }
    void print(){
        System.out.println("Dog #"+dogNumber);
    }
}

public class CatsAndDogs{
    public static void main(String[] args){
        Vector cats=new Vector();
        for(int i=0;i<7;i++){
           cats.addElement(new Cat(i));
        }
        cats.addElement(new Dog(7));
        for(int i=0;i<cats.size();i++)
            ((Cat)cats.elementAt(i)).print();
        //Dog is detected only at run-time
    }
}///:

用Vector方法elementAt()获取原本认为是Cat的对象时,实际获得的是指向一个Object的句柄,必须将那个对象cast为Cat在为Cat 调用print()方法之前进行强制造型;否则就会出现一个语法错误。在运行期间,如果试图将Dog 对象造型为Cat,就会得到一个异常(违例)。

//:WorksAnyway.java
//In special cases,things just seem to work correctly
import java.util.*;

class Mouse{
    private int mouseNumber;
    Mouse(int i){
        mouseNumber=i;
    }
    //Magic method:
    public String toString(){
        return "This is Mouse #"+mouseNumber;
    }
    void print(String msg){
        if(msg!=null) System.out.println("msg");
        System.out.println("Mouse number "+mouseNumber);
    }
}

class MouseTrap{
    static void caughtYa(Object m){
        Mouse mouse=(Mouse)m;//Cast from Object
        mouse.print("Caught one!");
    }
}
public class WorksAnyway{
    public static void main(String[] args){
        Vector mice=new Vector();
        for(int i=0;i<3;i++){
            mice.addElement(new Mouse(i));
        }
        for(int i=0;i<mice.size;i++){
            //No cast necessary,sutomatic call to Object.toString();
            System.out.println("Free mouse: "+mice.elementAt(i));
            MouseTrap.caughtYa(mice.elementAt(i));
        }
    }
}

Vector

//Vector
addElement();//插入对象
elementAt();//一次提取一个对象
elements();//获取对序列的一个枚举
//:HamsterMaze.java
//Using an Enumeration
import java.util.*;

class Hamster{
    private int hamsterNumber;
    Hamster(int i){
        hamsterNumber=i;
    }
    public String toString(){
        return "This is Hamster #"+hamsterNumber;
    }
}

class Printer{
    static void printAll(Enumeration e){
        while(e.hasMoreElements())
            System.out.println(e.nextElement().toString());
    }
}

public class HamsteMaze{
    public static void main(String[] args){
        Vector v=new Vector();
        for(int i=0;i<3;i++){
            v.addElement(new Hamster(i));
        }
        Printer.printAll(v.elements());
    }
}
///

枚举器

//Enumeration
elements();//要求集合为我们提供一个Enumeration
nextElement();//首次调用,返回序列中的第一个元素;获取下一对象
hasMoreElements();//检查序列中是否还有更多的对象
BitSet

BitSet 实际是由“二进制位”构成的一个Vector。如果希望高效率地保存大量“开-关”信息,就应使用BitSet。它只有从尺寸的角度看才有意义;如果希望的高效率的访问,那么它的速度会比使用一些固有类型的数组慢一些。

//详情请见知乎

但在Java 1.0 中,一旦BitSet 大于64 位,就会出现一些令人迷惑不解的行为。假如我们设置一个只比BitSet 当前分配存储空间大出1 的一个位,它能够正常地扩展。但一旦试图在更高的位置设置位,同时不先接触边界,就会得到一个恼人的违例。这正是由于BitSet 在Java 1.0 里不能正确扩展造成的。本例创建了一个512 位的BitSet。构建 器分配的存储空间是位数的两倍。所以假如设置位1024 或更高的位,同时没有先设置位1023,就会在Java1.0 里得到一个违例。但幸运的是,这个问题已在Java 1.1 得到了改正。所以如果是为Java 1.0 写代码,请尽量避免使用BitSet。

Stack
//:Stacks.java
//Demonstration of Stack Class
import java.util.*;

public class Stacks{
    static String[] months={
        "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
    };
    
    public static void main(String[] args){
        Stack stk=new Stack();
        for(int i=0;i<months.length;i++)
            stk.push(months[i]+" ");//压栈
        System.out.println("stk = "+stk);
        //Treating a stack as a Vector
        stk.addElement("The last line");
/*
这可能是由继承的特质决定的——Stack“属于”一种Vector。因此,能对Vector 进行的操作亦可针对Stack 进行,例如elementAt()方法。
*/
        System.out.println("element 5= "+stk.elementAt(5));
        System.out.println("popping elements: ");
        while(!stk.empty())
            System.out.println(stk.pop());//出栈
    }
}
Hashtable