7.Practical Java_实践 28-45:性能

版权声明:转载的文章,如果不同意请联系告知,谢谢。 https://blog.csdn.net/qq_20398345/article/details/81912221

实践 39:不要使用 Enumeration或 Iterato r来遍历 Vector
Java供遍历vector元素的数种办法:
1. Iterator(选代器)
2. ListIerator(list迭代器)
3. Enumeration(枚举器)
4. get()函数(取值函数, getter)

import java.util.Enumeration;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;

public class LoopVector {
    public int enumVec(Vector vec) {
        int total = 0;
        Enumeration enums =  vec.elements();
        while(enums.hasMoreElements()) {
            total += ((Integer)enums.nextElement()).intValue();
        }
        return total;
    }

    public int iterVec(Vector vec) {
        int total = 0;
        Iterator iter = vec.iterator();
        while(iter.hasNext()) {
            total += ((Integer) iter.next()).intValue();
        }
        return total;
    }

    public int listIterVec(Vector vec) {
        int total = 0;
        ListIterator iter = vec.listIterator();
        while(iter.hasNext()) {
            total += ((Integer)iter.next()).intValue();
        }
        return total;
    }

    public int forVec(Vector vec) {
        int total = 0;
        int size = vec.size();
        for (int i = 0; i < size; i++) {
            total += ((Integer) vec.get(i)).intValue();
        }
        return total;
    }

    public static void main(String[] args) {
        int VEC_SIZE = 100000;
        Vector<Integer> vec = new Vector<>(VEC_SIZE);
        for (int i = 1; i <= VEC_SIZE; i++) {
            vec.add(i);
        }

        long startTimer = 0;
        long endTimer = 0;
        int res = 0;

        LoopVector lv = new LoopVector();

        startTimer = System.currentTimeMillis();
        res = lv.enumVec(vec);
        endTimer = System.currentTimeMillis();
        System.out.println("invoke enumVec: res = " + res + ", cost=" + (endTimer-startTimer));

        startTimer = System.currentTimeMillis();
        res = lv.iterVec(vec);
        endTimer = System.currentTimeMillis();
        System.out.println("invoke iterVec: res = " + res + ", cost=" + (endTimer-startTimer));

        startTimer = System.currentTimeMillis();
        res = lv.listIterVec(vec);
        endTimer = System.currentTimeMillis();
        System.out.println("invoke listIterVec: res = " + res + ", cost=" + (endTimer-startTimer));

        startTimer = System.currentTimeMillis();
        res = lv.forVec(vec);
        endTimer = System.currentTimeMillis();
        System.out.println("invoke forVec: res = " + res + ", cost=" + (endTimer-startTimer));
    }
}

传入同一个vector,以上四个函数完成相同的任务.返回一样的结果。其中三个函数有不同的性能: Iterator版和 ListIterator版的性能大致相同, Enumeration版大约快 l 2%。至于采用Vectorget()的标准循环版本,比其他三个函数快 29%—34%.

invoke enumVec: res = 705082704, cost=7
invoke iterVec: res = 705082704, cost=8
invoke listIterVec: res = 705082704, cost=9
invoke forVec: res = 705082704, cost=5


实践 40:使用 System.arraycopy()来复制 arrays
copyAray2()比copyArray1()体积小,因为它毕竟是使用函数调用来完成工作,而非使用 inline方式。由于 copyArray2()调用的 System.arraycopy()是以本机函数( native method)实现的,因此它的执行速度更快。由于它是本机函数,所以它可以直接、
高效地移动[原始 array]的内在内容到[目标 array]。这个动作之快速足以消减本机函数的调用代价,明显比一般Java代码快得多。但也由于它是一个本机函数( nativemethod) ,所以这个调用动作的执行速度在不同的平台上有所不同。

public class CopyArrayTest {
    public void copyArray1(int[] src, int[] dest) {
        int size = src.length;
        for (int i = 0; i < size; i++) {
            dest[i] = src[i];
        }
    }
    public void copyArray2(int[] src, int[] dest) {
        int size = src.length;
        System.arraycopy(src, 0, dest, 0, size);
    }

    public static void main(String[] args) {
        int ARRAY_SIZE = 100000000;
        int[] src = new int[ARRAY_SIZE];
        int[] dest1 =  new int[ARRAY_SIZE];
        int[] dest2 =  new int[ARRAY_SIZE];

        for (int i = 0; i < ARRAY_SIZE; i++) {
            src[i] = i;
            dest1[i] = 0;
            dest2[i] = 0;
        }

        CopyArrayTest cat = new CopyArrayTest();
        long startTimer = 0;
        long endTimer = 0;

        startTimer = System.currentTimeMillis();
        cat.copyArray1(src, dest1);
        endTimer = System.currentTimeMillis();
        System.out.println("copyArray1, dest[ARRAY_SIZE-1] = " + dest1[ARRAY_SIZE-1] + ", timer = " + (endTimer - startTimer));

        startTimer = System.currentTimeMillis();
        cat.copyArray2(src, dest2);
        endTimer = System.currentTimeMillis();
        System.out.println("copyArray2, dest[ARRAY_SIZE-1] = " + dest2[ARRAY_SIZE-1] + ", timer = " + (endTimer - startTimer));

    }
}

/*
copyArray1, dest[ARRAY_SIZE-1] = 99999999, timer = 97
copyArray2, dest[ARRAY_SIZE-1] = 99999999, timer = 87
*/

实践41:优先使用 array,然后才考虑Vector和ArrayList
Vector和 ArrayList都采用 array作为底部设施,所以当这些 classes调整自身大小的时候,会创建一个新的 array, 然后将所有元素从原先的 array复制到新的 array中, 而后便可加入原本放不下的新元素了。
Vector和 ArrayList还有另一个不太起眼的副作用。 无论什么时候, 如果要从它们之中移除 ( removed)一个元素,所有[下标大于被删除元素]者都需要向前(向着起始处)移动一格。这样可以使得底部的 array不至于留下[空洞](holes)。

Vector的 get()是 synchronized,可以自动调整;----速度最慢
ArrayList的get()是unsynchronized,可以自动调整;----速度次之
Array不可以自动调整;-------速度最快
 

import java.util.ArrayList;
import java.util.Vector;

public class LoopArray {
    public void iterateArray(int[] arr) {
        int size = arr.length;
        int j;
        for (int i = 0; i < size; i++) {
            j = arr[i];
        }
    }
    public void iteratorVector(Vector vec) {
        int size = vec.size();
        Object j;
        for (int i = 0; i < size; i++) {
            j = vec.get(i);
        }
    }
    public void iterateArrayList(ArrayList alt) {
        int size = alt.size();
        Object j;


        for (int i = 0; i < size; i++) {
            j = alt.get(i);
        }
    }

    public static void main(String[] args) {
        int SIZE=1000000;

        int[] arr = new int[SIZE];
        Vector vec = new Vector(SIZE);
        ArrayList alt = new ArrayList(SIZE);

        for (int i = 0; i < SIZE; i++) {
            arr[i] = i;
            vec.add(i);
            alt.add(i);
        }

        long startTimer = 0;
        long endTimer = 0;
        LoopArray la = new LoopArray();

        startTimer = System.currentTimeMillis();
        la.iterateArray(arr);
        endTimer = System.currentTimeMillis();
        System.out.println("iterateArray timer = " + (endTimer - startTimer));

        startTimer = System.currentTimeMillis();
        la.iteratorVector(vec);
        endTimer = System.currentTimeMillis();
        System.out.println("iteratorVector timer = " + (endTimer - startTimer));

        startTimer = System.currentTimeMillis();
        la.iterateArrayList(alt);
        endTimer = System.currentTimeMillis();
        System.out.println("iterateArrayList timer = " + (endTimer - startTimer));
    }
}

/*
iterateArray timer = 3
iteratorVector timer = 8
iterateArrayList timer = 4
*/

实践 42:尽可能复用(reuse)对象
创建对象,代价不菲(参见实践32) ,因此你应该尽量减少创建次数。复用既有对象,而不重新创建一个。
 

class Employee {
    private String name;
    private String title;
    private int salary;

    public Employee() {}
    public Employee(String name, String title, int salary) {
        this.name  = name;
        this.title = title;
        this.salary = salary;
    }
    public void reinitialize(String name, String title, int salary) {
        this.name  = name;
        this.title = title;
        this.salary = salary;
    }
    public String getName() {return this.name;}
    public void setName(String name) {this.name = name;}
    public String getTitle() {return this.title;}
    public void setTitle(String title) {this.title = title;}
    public int getSalary() {return this.salary;}
    public void setSalary(int salary) {this.salary = salary;}
}
public class EmployeeTest {
    public int computePayroll1(String[] name, String[] title, int[] salary) {
        int size = name.length;
        int totalPayroll = 0;
        for (int i = 0; i < size; i++) {

            Employee em = new Employee(name[i], title[i], salary[i]);
            totalPayroll += em.getSalary();
//            System.out.println("computePayroll1: " + name[i] + ", " + title[i]+ ", " + salary[i] + "," + em.getSalary());
        }
        return totalPayroll;
    }

    public int computePayroll2(String[] name, String[] title, int[] salary) {
        int size = name.length;
        int totalPayroll = 0;
        if(size > 0)
        {
            Employee em = new Employee();
            for (int i = 0; i < size; i++) {
                em.setName(name[i]);
                em.setTitle(title[i]);
                em.setSalary(salary[i]);
                totalPayroll += em.getSalary();
//                System.out.println("computePayroll2: " + name[i] + ", " + title[i]+ ", " + salary[i] + "," + em.getSalary());
            }
        }
        return totalPayroll;
    }

    public int computePayroll3(String[] name, String[] title, int[] salary) {
        int size = name.length;
        int totalPayroll = 0;
        if(size > 0)
        {
            Employee em = new Employee();
            for (int i = 0; i < size; i++) {
                em.reinitialize(name[i], title[i], salary[i]);
                totalPayroll += em.getSalary();
//                System.out.println("computePayroll3: " + name[i] + ", " + title[i]+ ", " + salary[i] + "," + em.getSalary());
            }
        }
        return totalPayroll;
    }

    public static void main(String[] args) {
        int SIZE = 100000;
        String[] name  = new String[SIZE];
        String[] title = new String[SIZE];
        int[] salary   = new int[SIZE];
        for (int i = 0; i < SIZE; i++) {
            name[i]   = Integer.toString(i);
            title[i]  = Integer.toString(i);
            salary[i] = i;
        }

        EmployeeTest et = new EmployeeTest();
        long startTimer = 0;
        long endTimer = 0;
        int totalPayroll = 0;

        startTimer   = System.currentTimeMillis();
        totalPayroll = et.computePayroll1(name, title, salary);
        endTimer     = System.currentTimeMillis();
        System.out.println("computePayroll1, totalPayroll=" + totalPayroll + ", timer=" + (endTimer-startTimer));

        totalPayroll=0;
        startTimer   = System.currentTimeMillis();
        totalPayroll = et.computePayroll2(name, title, salary);
        endTimer     = System.currentTimeMillis();
        System.out.println("computePayroll2, totalPayroll=" + totalPayroll + ", timer=" + (endTimer-startTimer));

        totalPayroll=0;
        startTimer   = System.currentTimeMillis();
        totalPayroll = et.computePayroll3(name, title, salary);
        endTimer     = System.currentTimeMillis();
        System.out.println("computePayroll3, totalPayroll=" + totalPayroll + ", timer=" + (endTimer-startTimer));
    }
}


/*
computePayroll1, totalPayroll=704982704, timer=19
computePayroll2, totalPayroll=704982704, timer=12
computePayroll3, totalPayroll=704982704, timer=7
*/

猜你喜欢

转载自blog.csdn.net/qq_20398345/article/details/81912221