Java部分

  1. equals与==的区别

    ==是判断两个变量或实例是不是指向同一个内存空间
    equals是判断两个变量或实例所指向的内存空间的值是不是相同

  2. String、StringBuffer和StringBuilder的区别

    String 不可变 每次对其操作都会在数据池产生一个新的对象,不适合使用在对字符串进行频繁修改的场景
    StringBuffer和StringBuilder可变,对其修改不会产生新的对象 其两者区别在于StringBuffer线程安全而StringBuilder线程不安全

  3. Override和Overload的含义去区别

    override是重写(覆盖)方法名相同,实现不同。
    overload是重载,方法名相同,参数形式不同。

  4. 抽象类和接口的区别

    ①抽象类可以有构造方法,接口中不能有构造方法。
    ②抽象类中可以有普通成员变量,接口中没有普通成员变量
    ③抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
    ④抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
    ⑤抽象类中可以包含静态方法,接口中不能包含静态方法
    ⑥抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
    ⑦一个类可以实现多个接口,但只能继承一个抽象类。

  1. sleep()和wait()的区别

    对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
    sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
    在调用sleep()方法的过程中,线程不会释放对象锁。
    而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。

  2. HashMap Hashtable区别

    ① Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
    ② HashTable不允许null值(key和value都不可以) ,HashMap允许null值(key和value都可以)。
    ③ Hashtable中的方法是同步的(),而HashMap中的方法在默认情况下不是同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决。

  3. final、finally、finalize的区别

    ①final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
    ②finally是异常处理语句结构的一部分,表示总是执行。
    ③finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等

  4. Comparable和Comparator区别

    Comparable和Comparator都是用来实现集合中元素的比较、排序的。
    Comparable是在集合内部定义的方法实现的排序,位于java.util下。
    Comparator是在集合外部实现的排序,位于java.lang下。
    Comparable是自已完成比较,Comparator是外部程序实现比较。

  5. &&和&以及||和|的区别

    &&和&都是表示与,区别是&&只要满足第一个条件,后面条件就不再判断。而&要对所有的条件都进行判断。
    ||(短路或)和|(或)都是表示“或”,区别是||只要满足第一个条件,后面的条件就不再判断,而|要对所有的条件进行判断。

  6. 说出ArrayList,Vector,LinkedList的存储性能和特性

    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存 储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
    一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的
    二.数据增长:当需要增长时,Vector 默认增长为原来一培,而ArrayList却是原来的一半

  7. HashMap的底层源码实现

    当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

  8. 多态的实现机制

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法
  1. Switch能否用string做参数

    在 Java 7 之前, switch 只能支持byte,short,char,int 或者其对应的封装类以及 Enum 类型。在JAVA 7中,String 支持被加上了。

  2. Collection 和 Collections的区别

    ①Collection是集合类的上级接口,继承与他的接口主要有Set 和List.

    ②Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

  3. 同步和异步有何异同,在什么情况下分别使用他们?举例说明。

    如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

开篇导读

接触Android开发已经有些时日了,也算总结积累了一些小技巧,如今汇总分享给大家

include标签(避免重复渲染)和 ViewStub类(延迟加载)
  1. 当我们的页面变得复杂,XML文件内容过多时,标签可以有效地帮助我们整理文件内容,同时提高了XML文件的可读性。同时,它的用法也与Fragment类似。

  2. ViewStub是一个极佳的延迟加载视图资源的方式。只要你设计的视图是依赖于上下文来改变其可见性的,就利用ViewStub类吧。也许当你只将其应用在一个简单的页面当中时,并不会感觉到在性能上有任何提升,但是在复杂页面中,它的效果是极佳的。

开篇导读

Android提供了WebView控件用来处理Web网页,而在网页中,JavaScript一个很举足轻重的脚本。
本文将介绍如何通过JavaScript代码注入实现获取Html中标签值继而实现Java代码和Javascript代码的相互调用


操作步骤

  1. WebView开启Js调用:

    mWebView.getSettings().setJavaScriptEnabled(true);
    
  2. 定义JavaScript调用的交互接口及方法:

    public class JavaScriptInterface {
    
        @JavascriptInterface
        public void getTagVal(final String val) {
    
            if (!TextUtils.isEmpty(shareUrl)) {
                Log.e("log tag", "received from js. val = " + val);
            }
        }
    }
    
  3. WebView设置供JavaScript调用的交互接口。

    //后面 “android” 相当于一个标志符
    mWebView.addJavascriptInterface(new JavaScriptInterface(), "android");
    
  4. 在WebView加载完毕时注入JavaScript代码

    先看网页代码

    //这里是Html中我要通过注入取得的标签代码
    <meta name="tag" content="恭喜你注入成功,得到了返回值" />
    

    再来实现我们的java代码

    mWebView.setWebViewClient(new WebViewClient() {
    
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            //返回值为true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器
            return true;
        }
    
        @Override
        public void onPageFinished(WebView webView, String url) {
           //此处windows.android.getTagVal中android是第3步中设置的标记,getTagVal是第2步中的接口中的方法名
           //回调的参数中传的就是js代码,自行根据实际html标签脑补或百度
           String js = "window.android.getTagVal(document.getElementsByName('tag')[0].content))";
           webView.loadUrl("javascript:" + js);
        }
    });
    

OK!完美收官

简析


概念

归并排序 归并排序是利用递归和分而治之的技术将数据序列划分成为越来越小的半子表,再对半子表排序,最后再用递归步骤将排好序的半子表合并成为越来越大的有序序列,归并排序包括两个步骤,分别为:

原理

  1. 拆分:假设有N个元素的列表,首先把它拆分成2个或2个以上的元素组成的新的列表,分别对对它们进行排序。

  2. 归并:把所有的排好序的子类表两两归并,如此重复,直到归并成一个含N个元素的有序列表为止


范例(java)

概念代码

public static int[] sort(int[] nums, int low, int high) {  
    int mid = (low + high) / 2;  
    if (low < high) {  
        // 左边  
        sort(nums, low, mid);  
        // 右边  
        sort(nums, mid + 1, high);  
        // 左右归并  
        merge(nums, low, mid, high);  
    }  
    return nums;  
}  

public static void merge(int[] nums, int low, int mid, int high) {  
    int[] temp = new int[high - low + 1];  
    int i = low;// 左指针  
    int j = mid + 1;// 右指针  
    int k = 0;  

    // 把较小的数先移到新数组中  
    while (i <= mid && j <= high) {  
        if (nums[i] < nums[j]) {  
            temp[k++] = nums[i++];  
        } else {  
            temp[k++] = nums[j++];  
        }  
    }  

    // 把左边剩余的数移入数组  
    while (i <= mid) {  
        temp[k++] = nums[i++];  
    }  

    // 把右边边剩余的数移入数组  
    while (j <= high) {  
        temp[k++] = nums[j++];  
    }  

    // 把新数组中的数覆盖nums数组  
    for (int k2 = 0; k2 < temp.length; k2++) {  
        nums[k2 + low] = temp[k2];  
    }  
}  


// 归并排序的实现  
public static void main(String[] args) {  

    int[] nums = { 2, 7, 8, 3, 1, 6, 9, 0, 5, 4 };  

    MergeSort.sort(nums, 0, nums.length-1);  
    System.out.println(Arrays.toString(nums));  
}  

简析


概念

希尔排序(Shell Sort) 希尔排序的实质就是分组插入排序,该方法又称缩小增量排序。

原理

  1. 先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序

  2. 依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。

  3. 当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。


范例(java)

初始时,有一个大小为 10 的无序序列{9,1,2,5,7,4,8,6,5,3}。

在第一趟排序中,我们不妨设 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组

{9,4},{1,8},{2,6},{5,5},{7,3}

接下来,按照直接插入排序的方法对每个组进行排序

{4,9},{1,8},{2,6},{5,5},{3,7}

排序后位置交换原数组 {4,1,2,5,3,9,8,6,5,7}

在第二趟排序中,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 2 (取整数)。这样每相隔距离为 2 的元素组成一组,可以分为 2 组。

{4,2,3,8,5},{1,5,9,6,7}

按照直接插入排序的方法对每个组进行排序。

{2,3,4,5,8},{1,5,6,7,9}

排序后位置交换原数组 {2,1,3,5,4,6,5,7,8,9}

在第三趟排序中,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组。

{2,1,3,5,4,6,5,7,8,9}

按照直接插入排序的方法对每个组进行排序。此时,排序已经结束。

{1,2,3,4,5,5,6,7,8,9}

需要注意一下的是,图中有两个相等数值的元素 5 和 5 。我们可以清楚的看到,在排序过程中,两个元素位置交换了。
所以,希尔排序是不稳定的算法


概念代码

public static void main(String[] args) {
    int[] arr = {9, 1, 2, 5, 7, 4, 8, 6, 5, 3};
    int i, j, gap;
    int m = 1;//输出gap步数
    int count = arr.length;
    for (gap = count / 2; gap > 0; gap /= 2) { //步长
        for (i = 0; i < gap; i++) {//直接插入排序
            for (j = i + gap; j < count; j += gap)
                if (arr[j] < arr[j - gap]) {
                    int temp = arr[j];
                    int k = j - gap;
                    while (k >= 0 && arr[k] > temp) {
                        arr[k + gap] = arr[k];
                        k -= gap;
                    }
                    arr[k + gap] = temp;
                }
        }

        System.out.print("第" + m + "次排序结果:");
        for (int anArr : arr) {
            System.out.print(anArr + "\t");
        }
        System.out.println("");
        m++;
    }

    System.out.print("最终排序结果:");
    for (int anArr : arr) {
        System.out.print(anArr + "\t");
    }
}
1
2
3
4
第1次排序结果:4	1	2	5	3	9	8	6	5	7	
第2次排序结果:2 1 3 5 4 6 5 7 8 9
第3次排序结果:1 2 3 4 5 5 6 7 8 9
最终排序结果:1 2 3 4 5 5 6 7 8 9

简析


概念

直接选择排序(Select sort) 每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕。

原理

  1. 初始时,数组全为无序区为a[0..n-1]。令i=0

  2. 在无序区a[i…n-1]中选取一个最小的元素,将其与a[i]交换。交换之后a[0…i]就形成了一个有序区。

  3. i++并重复第二步直到i==n-1。排序完成。


范例(java)


概念代码

 public static void main(String[] args) {
    int arr[] = {23, 44, 56, 21, 32, 55, 74, 13};
    int count = arr.length;
    int i, j, min;
    for (i = 0; i < count; i++) {
        min = i;
        for (j = i + 1; j < count; j++) {
            if (arr[j] < arr[min]) {//找最小元素的位置
                min = j;
            }
        }

        int temp = arr[i];
        arr[i] = arr[min];
        arr[min] = temp;

        System.out.print("第" + (i + 1) + "次排序结果:");
        for (int anArr : arr) {
            System.out.print(anArr + "\t");
        }
        System.out.println("");
    }

    System.out.print("最终排序结果:");
    for (int anArr : arr) {
        System.out.print(anArr + "\t");
    }
}
1
2
3
4
5
6
7
8
9
第1次排序结果:13	44	56	21	32	55	74	23	
第2次排序结果:13 21 56 44 32 55 74 23
第3次排序结果:13 21 23 44 32 55 74 56
第4次排序结果:13 21 23 32 44 55 74 56
第5次排序结果:13 21 23 32 44 55 74 56
第6次排序结果:13 21 23 32 44 55 74 56
第7次排序结果:13 21 23 32 44 55 56 74
第8次排序结果:13 21 23 32 44 55 56 74
最终排序结果:13 21 23 32 44 55 56 74

简析


概念

插入排序(Insertion sort) 插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。 插入排序方法分直接插入排序和折半插入排序两种。

直接插入排序 把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。

折半插入排序(binary insertion sort) 是对插入排序算法的一种改进,由于排序算法过程中,就是不断的依次将元素插入前面已排好序的序列中。由于前半部分为已排好序的数列,这样我们不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。

直接插入排序原理

假设待排序的记录存放在数组a[0…n-1]。

  1. 初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1

  2. 将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。

  3. i++并重复第二步直到i==n-1。排序完成。

折半插入排序原理

  1. 将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m]

  2. 其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1)

  3. 如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]。


范例(java)


概念代码

    //直接插入排序
 public static void main(String[] args) {

    int arr[] = {23, 44, 56, 21, 32, 55, 74, 13};
    int count = arr.length;
    for (int i = 1; i < count; i++) {
        int temp = arr[i];
        int position = i;
        for (int j = i - 1; j >= 0; j--) {
            if (arr[j] > temp) {
                arr[j + 1] = arr[j];
                position -= 1;
            } else {
                break;
            }
        }
        arr[position] = temp;

        System.out.print("第" + i + "次排序结果:");
        for (int anArr : arr) {
            System.out.print(anArr + "\t");
        }
        System.out.println("");

    }

    System.out.print("最终排序结果:");
    for (int anArr : arr) {
        System.out.print(anArr + "\t");
    }
}
1
2
3
4
5
6
7
8
第1次排序结果:23	44	56	21	32	55	74	13	
第2次排序结果:23 44 56 21 32 55 74 13
第3次排序结果:21 23 44 56 32 55 74 13
第4次排序结果:21 23 32 44 56 55 74 13
第5次排序结果:21 23 32 44 55 56 74 13
第6次排序结果:21 23 32 44 55 56 74 13
第7次排序结果:13 21 23 32 44 55 56 74
最终排序结果:13 21 23 32 44 55 56 74
    //折半插入排序
  public static void main(String[] args) {

    int arr[] = {23, 44, 56, 21, 32, 55, 74, 13};
    int count = arr.length;
    int middle = 0;
    for (int i = 1; i < count; i++) {
        int low = 0;
        int high = i - 1;
        int temp = arr[i];

        while (low <= high) {
            middle = (low + high) / 2;
            if (temp < arr[middle]) {
                high = middle - 1;
            } else {
                low = middle + 1;
            }
        }

        int k = i;
        while (k > middle) {
            arr[k] = arr[k - 1];
            k--;
        }

        arr[high + 1] = temp;   //此处用 arr[low] = temp ;也可

        System.out.print("第" + i + "次排序结果:");
        for (int anArr : arr) {
            System.out.print(anArr + "\t");
        }
        System.out.println("");

    }

    System.out.print("最终排序结果:");
    for (int anArr : arr) {
        System.out.print(anArr + "\t");
    }
}
1
2
3
4
5
6
7
8
第1次排序结果:23	44	56	21	32	55	74	13	
第2次排序结果:23 44 56 21 32 55 74 13
第3次排序结果:21 23 44 56 32 55 74 13
第4次排序结果:21 23 32 44 56 55 74 13
第5次排序结果:21 23 32 44 55 56 74 13
第6次排序结果:21 23 32 44 55 56 74 13
第7次排序结果:13 21 23 32 44 55 56 74
最终排序结果:13 21 23 32 44 55 56 74

简析


概念

冒泡排序(Bubble sort) 是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

原理

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

范例(java)


概念代码

  public static void main(String[] args) {

    int arr[] = {23, 44, 56, 21, 32, 55, 74, 13};
    int count = arr.length - 1;
    for (int i = 0; i < count; i++) {
        //对当前无序区间arr[0.....count-i]进行排序(j的范围很关键,这个范围是在逐步缩小的)
        for (int j = 0; j < count - i; j++) {

            /**
             * 从小到大:arr[j] > arr[j + 1]
             * 从大到小:arr[j] < arr[j + 1]
             */

            //把大的值交换到后面
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }

        System.out.print("第" + (i + 1) + "次排序结果:");
        for (int anArr : arr) {
            System.out.print(anArr + "\t");
        }
        System.out.println("");

    }

    System.out.print("最终排序结果:");
    for (int anArr : arr) {
        System.out.print(anArr + "\t");
    }
}
1
2
3
4
5
6
7
8
第1次排序结果:23	44	21	32	55	56	13	74	
第2次排序结果:23 21 32 44 55 13 56 74
第3次排序结果:21 23 32 44 13 55 56 74
第4次排序结果:21 23 32 13 44 55 56 74
第5次排序结果:21 23 13 32 44 55 56 74
第6次排序结果:21 13 23 32 44 55 56 74
第7次排序结果:13 21 23 32 44 55 56 74
最终排序结果:13 21 23 32 44 55 56 74

优化代码

设置一个标志,如果一趟发生了交换,则为true,否则为false。则跳出while循环,明显如果有一趟没有发生交换,说明排序已经完成。

public static void main(String[] args) {

    int arr[] = {23, 44, 56, 21, 32, 55, 74, 13};
    int count = arr.length - 1;
    boolean flag = true;
    while (flag) {
        flag = false;
        for (int i = 0; i < count; i++) {
            if (arr[i] > arr[i + 1]) {
                int temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
                flag = true;
            }
        }
        count--;
    }
}

对于随机数列第一个最快,另一个要稍慢一点点,原因是内层循环多了个赋值语句(内层循环的指令数影响很明显的),而对于随机数列实际能减少的循环次数几乎可忽略(精测试1%数量级的)。