zoukankan      html  css  js  c++  java
  • java集合分析(转载)

    参考文章:浅谈Java中的Set、List、Map的区别

         Java 7 Collections详解

    java中集合分为三类:

    1. Set(集) 
    2. List(列表) 
    3. Map(映射)

    Set和List继承自Collection借口,Collection是基本的集合借口,声明适用于JAVA集合。

    Collection定义接口函数:

    • boolean add(Object o)      :向集合中加入一个对象的引用 
    • void clear():删除集合中所有的对象,即不再持有这些对象的引用 
    • boolean isEmpty()    :判断集合是否为空 
    • boolean contains(Object o) : 判断集合中是否持有特定对象的引用 
    • Iterartor iterator()  :返回一个Iterator对象,可以用来遍历集合中的元素 
    • boolean remove(Object o) :从集合中删除一个对象的引用 
    • int size()       :返回集合中元素的数目 
    • Object[] toArray()    : 返回一个数组,该数组中包括集合中的所有元素,关于:Iterator() 和toArray() 方法都用于集合的所有的元素,前者返回一个Iterator对象,后者返回一个包含集合中所有元素的数组。 

    1. Set是最简单的集合,集合中的对象不按特定方式排序,并且没有重复对象,Set接口主要实现两个类:

    • HashSet, 按照哈希算法存取集合中对象,速度较快
    • TreeSet,实现了SortedSet接口,可以对集合中对象进行排序Set存放对象的引用,没有重复对象.

    典型HashSet用例如下:

        static void findDups() {
            String[] str = {"d", "b", "c", "a", "d"};
            Set<String> s = new HashSet<String>();
            for (String a : str)
                if (!s.add(a))
                    System.out.println("Repeated: " + a);
            System.out.println("HashSet extends from Set: " + s);
            System.out.println("Unique elements: " + s.size());
    
            s.removeAll(Collections.singleton("d"));
            System.out.println(s);
    
            s.addAll(Collections.singleton("w"));
            System.out.println(s);
    
            String newStr = s.toString();
            System.out.println(newStr);
        }
    View Code

     HashSet和TreeSet性能差距,可以看如下代码分析,插入方面,Hash大概比后者快4倍:

     final StopWatch stopwatch = new StopWatch();
            stopwatch.start();
    
            Set set = new HashSet();
            String s1 = new String("Hello");
            String s2 = s1;
            String s3 = new String("world");
            // Stop watch split
            stopwatch.split();
            System.out.println("HashSet create: " + stopwatch.getSplitNanoTime());
    
            // HashSet add value
            set.add(s1);
            set.add(s2);
            set.add(s3);
            // Stop watch split
            stopwatch.split();
            System.out.println("HashSet add: " + stopwatch.getSplitNanoTime());
    
            Set set2 = new TreeSet();
            // Stop watch split
            stopwatch.split();
            System.out.println("TreeSet create: " + stopwatch.getSplitNanoTime());
            set2.add(s3);
            set2.add(s3);
            set2.add(s1);
            // Stop watch split
            stopwatch.split();
    View Code

    2. List 特征是线性存储元素,集合中可以存在重复对象。

    2.1 List接口主要实现类包括:

    ArrayList:代表长度可以改变的数组,可以对元素进行随机访问,往list总插入删除元素较慢。

    LinkedList 采用链表数据结构实现,插入和删除速度较慢,访问速度慢。

    在搜索频繁的情况下,选择使用ArrayList;插入删除频繁的情况下,选择使用ListArray。值得提一下的的是,从java2开始,Vector向量改进为可以实现List。除了继承Collection, List实现了很多自带函数,例如截取函数。

    •     int indexOf(Object o);
    •     int lastIndexOf(Object o);
    •     ListIterator<E> listIterator();
    •     ListIterator<E> listIterator(int index);
    •     List<E> subList(int from, int to);

    List 常用操作如下:

      static <E> void swap(List<E> a, int i, int j) {
            E temp = a.get(i);
            a.set(i, a.get(j));
            a.set(j, temp);
        }
    
        static void shuffle(List<?> list, Random rnd) {
            for (int i = list.size(); i > 1; i--){
                int rndNum = rnd.nextInt(i);
                //System.out.println(rndNum);
                try{
                    swap(list, i - 1, rndNum);
                } catch (IndexOutOfBoundsException exc){
                    exc.printStackTrace();
                }
            }
        }
    
        static void ListOpts() {
            List<String> list = new ArrayList<String>();
            String[] str = {"a","b","c","d","e","f"};
            for (String a : str) {
                list.add(a);
            }
            List<String> list1 = new ArrayList<String>(Arrays.asList(str));
            shuffle(list, new Random());
            shuffle(list1, new Random());
            System.out.println(list);
            System.out.println(list1);
    
            int indexOf = list.indexOf("e");
            int indexOf1 = list1.indexOf("e");
            System.out.println(indexOf);
            System.out.println(indexOf1);
        }
    View Code

    2.2 此外,List还有ListIterator这个增强型Iterator,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator 没有当前元素;它的光标位置 始终位于调用 previous() 所返回的元素和调用 next() 所返回的元素之间。长度为 n 的列表的迭代器有 n+1 个可能的指针位置(如图,长度为4的列表的迭代器有5个可能的指针位置)。

    逆序访问List实现代码如下:

        static <E> void ListIterator(List<E> list) {
            for (ListIterator<E> it = list.listIterator(list.size()); it.hasPrevious();) {
                E t = it.previous();
                System.out.print(t + " ");
            }
        }
    View Code

    同时ListIterator提供Set和Add两种方法,下面代码演示如何将List中元素替换为其他值:

       static <E> void ListReplace(List<E> list, E val, E newVal) {
            for (ListIterator<E> it = list.listIterator(); it.hasNext(); ) {
                if (val == null ? it.next() == null : val.equals(it.next()))
                    it.set(newVal);
            }
        }
    View Code

    当然,我们还可以将某个元素替换位一系列元素:

        static <E> void ListReplaceWithList(List<E> list, E val, List<? extends E> newVals) {
            for (ListIterator<E> it = list.listIterator(); it.hasNext(); ) {
                if (val == null ? it.next() == null : val.equals(it.next())){
                    it.remove();
                    for (E e : newVals)
                        //System.out.println(e);
                        it.add(e);
                }
            }
        }
    View Code

    可以这样搜索List表里的指定元素:

    res = list.subList(fromIndex, toIndex).indexOf(object);

    如果返回-1表示没有找到,否则返回指定元素在List中下标。

    2.3 任意一个操作List的多肽算法,如replace和shuffle方法,都是与字表打交道的。这里给出一个使用subList的多肽方法,使用这个方法来处理经典发扑克牌的问题。首先,先假设只给一个人发牌(hand),扑克牌堆用deck表示,那么发n张牌就可以看做从deck表的尾部截取n个元素的子List。代码如下:

        static <E> List<E> dealHand(List<E> deck, int n) {
            int deckSize = deck.size();
            List<E> handView = deck.subList(deckSize - n, deckSize);
            System.out.println("handView: " + handView);
            List<E> hand = new ArrayList<E>(handView);
            handView.clear();
            return hand;
        }
    View Code

    注意:我们操作从sublList获取List时候,例如运行clear,父List同样会清空。

    Ok, 接下来我们模拟发牌行为,代码如下:

        static <E> void dealing(List<E> deck, int numHands, int cardsPerPerson) {
            Collections.shuffle(deck);
            if (numHands * cardsPerPerson > deck.size()){
                System.out.println("Too many hands to play!");
                return ;
            }
            for (int i = 0; i < numHands; i++){
                System.out.println(dealHand(deck, cardsPerPerson));
            }
        }
    View Code

    最后贴上原文作者链接图:

  • 相关阅读:
    Go的Web之旅【部署】
    module declares its path as: github.com/xxx/yyy【Go报错】
    android studio快捷键集合
    Web App 概述
    WIN10 kafka搭建完后命令测试步骤自用
    Echarts tab 切换解决图不能显示的问题
    如何为不定高度(height:auto)的元素添加CSS3 transition-property:height 动画
    手持设备开发项目实例
    SQL Server 查找表问题
    Tomcat 10 升级注意事项
  • 原文地址:https://www.cnblogs.com/wenwangt/p/5043870.html
Copyright © 2011-2022 走看看