【面试之java容器】数组、字符容器,对象容器

来源:互联网 发布:js重置form表单 编辑:程序博客网 时间:2024/04/29 02:57

1.数组

     ·几种定义方式

/** * Created by 111 on 2016/2/24. */public class ArrayTest {    public static void main(String [] args){        int [] arr1;                                    //未初始化不可以使用        String [] arr3,arr4 = new String[]{"aaa","bbb"};//可以定义多个数组,变量已知        int arr5[] = new int[]{};                       //已初始化,只能定义一个数组        int [] arr2 = new int[4];        for (int i = 0,length=arr2.length;i<length;i++){//为数组插入数据            arr2[i] = 4;        }        System.out.println(arr2.length);                //数组长度(0-(length-1))    }}

2.String

    ·String一旦被初始化就不会被改变(String属于对象,对象的不可改变是指对象的状态不可改变,更具体就是对象内部成员变量不可改变)

          解析源码(java 1.7 一部分):

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence {    /** The value is used for character storage. */    private final char value[];    /** Cache the hash code for the string */    private int hash; // Default to 0    /** use serialVersionUID from JDK 1.0.2 for interoperability */    private static final long serialVersionUID = -6849794470754667710L;}
               ★从源码中可以看出String是利用了数组来存储,而用于存储的value是final类型(被final修饰的变量属于常量,被final修饰的方法不能被覆盖,被final修饰的类不能被继承),源码中也并没有提供value的get/set方法,所以一旦值固定,就不能被改变。

               ★但是为什么replace/replaceAll等其他String提供的方法仍然能返回同一个呢,我们知道对象有对象和对象的引用(保存的是对象的地址)之分,对象储存在堆中,对象的引用存储在栈中,这里其实是对象的引用指向了另一个新的对象。查看源码可知:其利用了StringBuffer来操作String中的数据。

java.lang.String 的replace源码:

 /**     * Replaces each substring of this string that matches the literal target     * sequence with the specified literal replacement sequence. The     * replacement proceeds from the beginning of the string to the end, for     * example, replacing "aa" with "b" in the string "aaa" will result in     * "ba" rather than "ab".     *     * @param  target The sequence of char values to be replaced     * @param  replacement The replacement sequence of char values     * @return  The resulting string     * @throws NullPointerException if <code>target</code> or     *         <code>replacement</code> is <code>null</code>.     * @since 1.5     */    public String replace(CharSequence target, CharSequence replacement) {        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));    }

java.util.regex.Matcher 的replaceAll()方法

/**     * Replaces every subsequence of the input sequence that matches the     * pattern with the given replacement string.     *     * <p> This method first resets this matcher.  It then scans the input     * sequence looking for matches of the pattern.  Characters that are not     * part of any match are appended directly to the result string; each match     * is replaced in the result by the replacement string.  The replacement     * string may contain references to captured subsequences as in the {@link     * #appendReplacement appendReplacement} method.     *     * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in     * the replacement string may cause the results to be different than if it     * were being treated as a literal replacement string. Dollar signs may be     * treated as references to captured subsequences as described above, and     * backslashes are used to escape literal characters in the replacement     * string.     *     * <p> Given the regular expression <tt>a*b</tt>, the input     * <tt>"aabfooaabfooabfoob"</tt>, and the replacement string     * <tt>"-"</tt>, an invocation of this method on a matcher for that     * expression would yield the string <tt>"-foo-foo-foo-"</tt>.     *     * <p> Invoking this method changes this matcher's state.  If the matcher     * is to be used in further matching operations then it should first be     * reset.  </p>     *     * @param  replacement     *         The replacement string     *     * @return  The string constructed by replacing each matching subsequence     *          by the replacement string, substituting captured subsequences     *          as needed     */    public String replaceAll(String replacement) {        reset();        boolean result = find();        if (result) {            StringBuffer sb = new StringBuffer();            do {                appendReplacement(sb, replacement);                result = find();            } while (result);            appendTail(sb);            return sb.toString();        }        return text.toString();    }
                  ★这里说不能被改变,是自身不能改变,但是我们可以利用反射来改变,这里被final修饰的也是一个数组对象,属于引用变量,这里final只能限制不能指向其他的数组对象,但是我们可以对数组中的内容进行修改。通过反射的方法获取到value这个数组字段,然后对数组中的数据进行修改。

参考代码:

import java.lang.reflect.Field;/** * Created by 111 on 2016/2/28. */public class Demo2 {    public static void main(String[]args)throws Exception{        String s = "ABCDEFG";//        Class stringClass = Class.forName("java.lang.String");//        Class stringClass = s.getClass();        Class stringClass = String.class;//三种获取类的方式        Field valueField = stringClass.getDeclaredField("value");//获取需要的字段        valueField.setAccessible(true);    //设置可访问权限        char [] value = (char[])valueField.get(s);//获得该字段的值        value[0] = 'B';        System.out.println(s);//输出BBCDEFG    }}
      · string内部提供的方法:

       ——length();

       ——isEmpty();

       ——charAt():0<=x<length();

       ——getBytes(String charsetName):

       。。。

    ·关于字符串的一些操作

           ★将字符串反转(String并未提供该方法,StringBuffer提供了该方法reverse())

                ①仿照StringBuffer中的reverse()方法

import java.lang.reflect.Field;/** * Created by 111 on 2016/2/28. */public class Demo3 {    public static void main(String [] args) throws Exception{        String s = "ABCDE";        Class sClass = Class.forName("java.lang.String");        Field valueField = sClass.getDeclaredField("value");        valueField.setAccessible(true);        char [] value = (char[])valueField.get(s);        int l = s.length()-1;        for (int j=(l-1)>>1;j>=0;--j){//有符号右移,高位补0,若无符号右移,高位补1            char temp = value[j];            char temp2 = value[l-j];//StringBuffer中下面会有一个验证            value[l-j] = temp;            value[j] = temp2;        }        System.out.println(s);    }}

            ②使用递归

/** * Created by 111 on 2016/2/29. */public class Demo4 {    public static void main(String [] args){        String s = "ABCDE";        String str = reverse(s);        System.out.println(str);    }    private static String reverse(String s){        if (s.isEmpty())return s;        return reverse(s.substring(1))+s.charAt(0);    }}

       ③遍历

   

/** * Created by 111 on 2016/2/29. */public class Demo5 {    public static void main(String [] args){        String str = "ABCDE";        String s = ""; //如果数据量大的话可以使用StringBuilder,多线程使用StringBuffer        for (int i =str.length()-1;i>=0;i--){            s+=str.charAt(i);                //sb.append(str.charAt(i));        }        System.out.println(s);    }}
       ★字符串去重

         ①放入Set集合中

import java.util.HashSet;import java.util.Set;/** * Created by 111 on 2016/2/29. */public class Demo6 {    public static void main(String [] args){        String str = "AABCDAEFE";        Set set = new HashSet();        for (int i=0,l=str.length();i<l;i++){            set.add(str.charAt(i));        }        System.out.println(set.toString());    }}

             ②循环判断

import java.util.ArrayList;import java.util.List;/** * Created by 111 on 2016/2/29. */public class Demo7 {    public static void main(String[]args){        String str = "AABCDAEFE";        List<String> list = new ArrayList<String>();        for (int i = 0,len=str.length();i<len;i++){            if (!list.contains(String.valueOf(str.charAt(i)))){  //char转为String                list.add(String.valueOf(str.charAt(i)));            }        }        System.out.println(list.toString());    }}

3.StringBuffer、StringBuilder   (append)(初始化容量为16字符

       ·与String相比特点:★长度可变

                           ★可以存储不同基本数据类型

                           ★可以对字符串进行修改(append,delete,insert,replace)

    

       ·StringBuffer:线程安全

       ·StringBuilder:单线程

4.Collection 集合类(add)(Vector和ArrayList 初始化容量为10

   ·特点:★存储对象,不可以存储基本数据类型

          ★长度可变

   ·Collection

         ··List(有序、元素有角标、元素可重复)指的是存入和取出的顺序一致:特有方法可操作角标的方法   Iterator it = list.iterator()

              ···Vector    : list接口大小可变数组的实现,包括null,是同步的,所以查询速度相对较慢(被sychronized修饰)

              ···ArrayList : list接口大小可变数组的实现,包括null,不同步的,数组有角标,所以查询速度快

              ···LinkedList:  list的链接列表的实现,     包括null,  不同步的,链表实现所以增删速度快

         ··Set(无序、元素不可重复)

              ···HashSet   : 包括null, 不同步的,基于哈希表(实际上是HashMap 实例)(开辟一个原有4/3大小的集合,默认16)

                    ····LinkedHashSet

5.Map

    ·Map<Key,Value>  :an object that maps keys to values,key 不能重复。一个key最多映射一个value

           ·HashMap    :哈希表的实现,允许空键和空值,是不同步的

           ·Hashtable  :哈希表的实现 ,非空对象可以作为键或者值,同步的

                  ·Properties

           ·treeMap :二叉树的底层实现,可用于给Map集合中键进行排序

           ★map的几种遍历方法

package com.raipeng.work.container;import java.util.*;/** * Created by 111 on 2016/2/29. */public class ListTest {    public static void main(String [] args){        Map<Integer,String> map = new HashMap();        map.put(1,"abc");        map.put(2,"def");        //keySet()        Set<Integer> keySet = map.keySet();        for (Integer key :keySet){//keySet的for循环            System.out.println("key:"+key+"value:"+map.get(key));        }        Iterator<Integer> it = keySet.iterator();//keySet的iterator        while (it.hasNext()){            Integer key =it.next();            System.out.println(key+map.get(key).toString()+"");        }        //entrySet()        Set<Map.Entry<Integer,String>> entry = map.entrySet();        for (Map.Entry<Integer,String> en:map.entrySet()){//entrySet的for循环            System.out.println("key:"+en.getKey()+"value:"+en.getValue());        }        Iterator<Map.Entry<Integer,String>> iterator = entry.iterator();//entrySet的iterator        while (iterator.hasNext()){            Map.Entry<Integer,String> entry1 = iterator.next();            Integer key = entry1.getKey();            String value = entry1.getValue();            System.out.println("key"+key+"value"+value);        }    }}


     

0 0