17 容器

17.3 Collection的功能方法
CollectionMethods
class CollectionMethods {
    public static void chapter17_3() {
        Collection<String> c = new ArrayList<>();
        c.add("ten");
        c.add("tens");
        System.out.println(c.toString());

        Object[] arr = c.toArray();
        System.out.println(arr.toString());
        for(int i=0;i< arr.length;i++){
            System.out.println(arr[i].toString());
        }
        String[] str = c.toArray(new String[0]);
        for(int i=0;i< arr.length;i++){
            System.out.println(str[i]);
        }

        c.clear();
        System.out.println(c.toString());
    }
}
17.4 可选操作
执行各种不同的添加和移除的方法在Collection接口中都是可选操作。这意味着实现类并不需要为这些方法提供功能定义。
将方法定义为可选的,是为了防止在设计类时出现接口爆炸的情况。
如果一个操作是未或支持的,那么调用接口的时候可能会导致UnsupportedOperationException异常。
注意:未获支持的操作只有在运行时才能探测到,即动态类型检查。
17.4.1 未获支持的操作
最常见的未获支持的操作,都来源于背后由固定尺寸的数据结构支持的容器。
Unsupported
class Unsupported {
    static void test(String msg, List<String> list) {
        Collection<String> c = list;
        Collection<String> subList = list.subList(1,8); //[1,8)
        Collection<String> c2 = new ArrayList<>(subList);
        System.out.println("msg:" + msg);
        System.out.println(c.toString());

        try {
            c.retainAll(c2);
            System.out.println(c.toString());
        }catch (Exception e) {
            System.out.println("retainAll:" + e);
        }

        try {
            c.removeAll(c2);
            System.out.println(c.toString());
        }catch (Exception e) {
            System.out.println("removeAll:" + e);
        }

        try {
            c.add("A");
            c.add("C");
            System.out.println(c.toString());
        }catch (Exception e) {
            System.out.println("add:" + e);
        }

        try {
            c.remove("A");
            System.out.println(c.toString());
        }catch (Exception e) {
            System.out.println("remove:" + e);
        }

        try {
            list.set(0,"Z");
            System.out.println(list.toString());
        }catch (Exception e) {
            System.out.println("list.set:" + e);
        }
    }
    public static void chapter17_4() {
        List<String> list = Arrays.asList("A B C D E F G H I J".split(" "));
        test("Modifiable", new ArrayList<>(list));
        test("Arrays.asList", list);
        test("Unmodifiable", Collections.unmodifiableList(new ArrayList<>(list)));
    }
}

Arrays.asList()返回固定尺寸的List,仅支持那些不会改变数组大小的操作;

unmodifiableList()结果在任何情况都不可修改。

 
17.5 List
Lists
class Lists {
    static void basicTest(List<String> list) {
        System.out.println(list);
        list.add(1,"a");
        list.add("hyh");
        List<String> ls = Arrays.asList("ab cd".split(" "));
        list.addAll(ls);
        System.out.println(list);
        String s = list.get(2);
        int index = s.indexOf("hyh");
        System.out.println("s:" + s + " index:" + index);
    }
    static void iterMotion(List<String> list) {
        ListIterator<String> iter = list.listIterator();
        Boolean b = iter.hasNext();
        String s = iter.next();
        Integer i = iter.nextIndex();
        System.out.println("b:" + b + " s:" + s + " i:" + i);
    }
    static void iterManipulation(List<String> list) {
        ListIterator<String> iter = list.listIterator();
        iter.add("7");
        System.out.println(list);
        //删除"7"下一个元素
        iter.next();
        iter.remove();
        System.out.println(list);
        //替换"7"下一个元素
        iter.next();
        iter.set("xjy");
        System.out.println(list);
    }
    public static void chapter17_5() {
        List<String> list = Arrays.asList("a b c d e f".split(" "));
        //修改容器大小的操作不可直接传入Arrays.asList固定容器
        basicTest(new LinkedList<>(list));
        iterMotion(list);
        //修改容器大小的操作不可直接传入Arrays.asList固定容器
        iterManipulation(new LinkedList<>(list));
    }
}

基本用法

 
17.6 Set
HashSet:快速查找,存入HashSet的元素必须定义hashCode(),equals()
TreeSet:保持次序的Set,元素必须实现Comparable接口
LinkedHashSet:保持插入次序的Set,存入HashSet的元素必须定义hashCode(),equals()
SortedSetDemo
class SortedSetDemo {
    public static void chapter17_6() {
        SortedSet<String> sortedSet = new TreeSet<>();
        Collections.addAll(sortedSet, "one two three four five".split(" "));
        System.out.println(sortedSet);
        System.out.println(sortedSet.first());
        System.out.println(sortedSet.last());
        String low = null,high = null;
        Iterator<String> iter = sortedSet.iterator();
        for(int i=0;i<sortedSet.size();i++) {
            String str = iter.next();
            if(i==1) {
                low = str;
            }
            if(i==sortedSet.size()-1) {
                high = str;
            }
        }
        System.out.println("low:" + low + " high:" + high);
        System.out.println(sortedSet.subSet(low,high));
        System.out.println(sortedSet.headSet(high));
        System.out.println(sortedSet.tailSet(low));
    }
}
first():返回容器中第一个元素
last():返回容器中最后一个元素
subSet(from,to): [from,to)的子集
headSet(to):小于to的子集
tailSet(from):大于等于from的子集
 
17.7 Queue
QueueBehavior
interface Generator<T> {
    T next();
}
class QueueBehavior {
    static void test(Queue queue, Gen gen) {
        for(int i=0;i<gen.size();i++) {
            queue.offer(gen.next());
        }
        while(queue.peek()!=null) {
            System.out.print(" " + queue.remove());
        }
        System.out.println("");
    }
    static class Gen implements Generator<String> {
        String[] str = "one two three four five".split(" ");
        int i = 0;
        public int size() {
            return str.length;
        }
        @Override
        public String next() {
            return str[i++];
        }
    }
    public static void chapter17_7() {
        test(new LinkedList(), new Gen());
        test(new PriorityQueue(), new Gen());
    }
}
LinkedList:插入顺序
PriorityQueue:自然顺序
 
ToDoList
class ToDoItem implements Comparable<ToDoItem> {
    private char primary;
    private int secondary;
    private String item;

    public ToDoItem(String td, char pri, int sec) {
        primary = pri;
        secondary = sec;
        item = td;
    }
    @Override
    public int compareTo(ToDoItem o) {
        if(primary > o.primary) {
            return 1;
        }else if(primary == o.primary) {
            if(secondary > o.secondary) {
                return 1;
            }else if(secondary == o.secondary) {
                return 0;
            }
        }
        return -1;
    }
    public String  toString() {
        return Character.toString(primary) + secondary + " :" + item;
    }
}
class ToDoList extends PriorityQueue<ToDoItem> {
    void add(String td, char pri, int sec) {
        super.add(new ToDoItem(td,pri,sec));
    }
    public static void chapter17_7() {
        ToDoList toDoList = new ToDoList();
        toDoList.add("han1",'C',4);
        toDoList.add("han2",'A',1);
        toDoList.add("han3",'A',2);
        toDoList.add("han4",'B',3);
        toDoList.add("han5",'B',4);
        while(!toDoList.isEmpty()){
            System.out.println("" + toDoList.remove());
        }
    }
}
PriorityQueue:实现Comparable
 
17.8 Map
Maps
class Maps {
    static void printKeys(Map<Integer,String> map) {
        System.out.println("map.size():" + map.size());
        System.out.println("map.keySet():" + map.keySet());
        System.out.println("map.values():" + map.values());
    }
    static void test(Map<Integer,String> map) {
        map.put(3,"han3");
        map.put(4,"han4");
        map.put(1,"han1");
        map.put(2,"han2");
        printKeys(map);

        Integer first = map.keySet().iterator().next();
        map.remove(first);
        printKeys(map);

        map.clear();
        printKeys(map);
    }
    public static void chapter17_8() {
        System.out.println("HashMap:");
        test(new HashMap<>());
        System.out.println("LinkedHashMap:");
        test(new LinkedHashMap<>());
        System.out.println("TreeMap:");
        test(new TreeMap<>());
    }
}
HashMap:基于散列表的实现
LinkedHashMap:插入次序
TreeMap:基于红黑树的实现,次序由Comparable或Comparator决定
WeakHashMap:弱键映射,允许释放映射所指向的对象
ConcurrentHashMap:线程安全Map
 
17.9 散列与散列码
注意:如果使用自己的类作为HashMap的键,必须同时重载hashCode()和equals()。否认使用散列的数据结构(HashSet,HashMap,LinkedHashSet或LInkedHashMap)无法正确处理你的键。
使用散列的目的:想要使用一个对象来查找另一个对象。
散列的价值在于速度,使得查询得以快速进行。
我们希望在Map中保存数量不确定的值,如果键的数量别数组的容量限制了,怎么办?
答案是:数组不保存键本身,而是通过键对象生成一个数字,将其作为数组的下标。这个数字就是散列码,由定义在Object中,可能由你的类覆盖的 hashCode()方法生成。 为解决数组容量固定的问题,不同的键可以产生相同的下标。也就是说,可能会有冲突。 如果能够保证没有冲突,那就是一个完美的散列函数。 通常,冲突由外部链接处理,数组保存值的list,然后对list里的值使用 equals() 方法进行线性查询。
如果散列函数好的话,数组的每个位置只有较少的值。因此,不是查询整个list,而是快速跳到数组的某个位置,只对很少的元素进行比较。这便是HashMap快的原因。
设计hashCode:无论何时,对同一个对象调用hashCode()都应该生成同样的值。
Joshua Bloch recipe:
(1)result = 17;
(2)计算int散列码c;
(3)合并计算散列码:
result = 37*result + c;
(4)返回result;
(5)检查hashCode(),确保相同的对象有相同的散列码;
CountedString
class CountedString {
    private static List<String> created = new ArrayList<>();
    private String s;
    private int id = 0;

    public CountedString(String str) {
        s = str;
        created.add(s);
        for(String t:created) {
            if(t.equals(s)) {
                id++;
            }
        }
    }

    public String toString() {
        return "String:" + s + " id:" + id + " hashCode():" + hashCode();
    }

    public int hashCode() {
        int result = 17;
        result = 37*result + s.hashCode();
        result = 37*result + id;
        return result;
    }

    public boolean equals(Object o) {
        return o instanceof CountedString && s.equals(((CountedString)o).s) && id == ((CountedString)o).id;
    }

    public static void chapter17_9() {
        Map<CountedString,Integer> map = new HashMap<>();
        CountedString[] cs = new CountedString[5];
        for(int i=0;i<cs.length;i++) {
            cs[i] = new CountedString("ha");
            map.put(cs[i],i);
        }
        System.out.println(map);

        for(CountedString c:cs) {
            System.out.println("key:" + c + " value:" + map.get(c));
        }
    }
}
 
17.11 实用方法
Utilities
class Utilities {
    public static void chapter17_11() {
        List<String> list = Arrays.asList("one Two three Four five".split(" "));
        System.out.println("list:" + list);
        System.out.println("disjoint:" + Collections.disjoint(list,Collections.singletonList("Four")));
        System.out.println("max:" + Collections.max(list));
        System.out.println("max_insensitive:" + Collections.max(list,String.CASE_INSENSITIVE_ORDER));
        System.out.println("min:" + Collections.min(list));
        System.out.println("min_insensitive:" + Collections.min(list,String.CASE_INSENSITIVE_ORDER));

        List<String> sublist = Arrays.asList("Four five".split(" "));
        System.out.println("indexOfSubList:" + Collections.indexOfSubList(list,sublist));
        Collections.reverse(list);
        System.out.println("reverse:" + list);
        Collections.rotate(list,2);
        System.out.println("rotate:" + list);

        List<String> src = Arrays.asList("xxx yyy zzz".split(" "));
        Collections.copy(list,src);
        System.out.println("copy:" + list);
        Collections.swap(list,0,list.size()-1);
        System.out.println("swap:" + list);
        Collections.shuffle(list,new Random(7));
        System.out.println("shuffle:" + list);
    }
}
java.util.Collections类内部的静态方法
disjoint:当两个集合没有任何相同元素时,返回true
shuffle:随机改变列表顺序
 
FailFast
class FailFast {
    public static void chapter17_11() {
        Collection<String> c = new ArrayList<>();
        Iterator<String> it = c.iterator();
        c.add("ha");
        try {
            it.next();
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("e:" + e.getMessage() + " " + e.toString());
        }
    }
}
扫描二维码关注公众号,回复: 12722856 查看本文章
容器保护机制,快速报错。在迭代遍历容器时,容器大小被(其他线程或自己)改变,会触发快速报错。
此例中,应该在添加完所有的元素后,再获取迭代器。
 
17.12 持有引用
java.lang.ref类库包含了一组类,这些类为垃圾回收提供了更大的灵活性。三个继承自抽象类Reference的类:SoftReference,WeakRefenrence,PhantomReference。
对象是可获得的,是指对象在程序中的某处能找到。意味着在栈中的一个引用,或有更多的中间链接。如果一个对象是"可获得的",垃圾回收器就不能回收它。 如果想继续持有对某个对象的引用,又希望垃圾回收器能自动回收它,则考虑使用Reference对象。

猜你喜欢

转载自blog.csdn.net/u012906122/article/details/114217089
17