zoukankan      html  css  js  c++  java
  • Java基础2——集合框架

    Collection和Map是集合的顶层接口

    先看Collection,这个接口定义了以下方法:

    添加功能:

      boolean add(Object obj):添加一个元素

      boolean addAll(Collection c):添加一个集合的元素

    删除功能

      void clear():移除所有元素

      boolean remove(Object o):移除一个元素

      boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)

    判断功能

      boolean contains(Object o):判断集合中是否包含指定的元素

      boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(是一个还是所有)

      boolean isEmpty():判断集合是否为空

    获取功能

      Iterator<E> iterator()(重点)

    长度功能

      int size():元素的个数

      面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?

    交集功能

      boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?

    把集合转换为数组

      Object[] toArray()

    List和Set是Collection集合的两个子接口

      List是一个有序的队列,每一个元素都有它的索引,第一个元素的索引值是0

      ArrayList、Vector、LinkedList、Stack是List的四个实现类,其中比较常用的是ArrayList(线性表)、LinkedList(链表)

      Set是一个不允许有重复元素的集合

      Set的实现类有HastSet和TreeSet,其中比较常用的是HashSet

    Collection通用方法举例

            Collection c=new ArrayList();
            Student s1=new Student("aaa",15);
            Student s2=new Student("bbb",16);
            Student s3=new Student("ccc",17);
            Student s4=new Student("ddd",18);
            Student s5=new Student("eee",19);
            Student s6=new Student("fff",20);
            //添加一个或多个元素
            c.add(s1);
            c.add(s2);
            //========
            Collection c1=new ArrayList();
            c1.add(s3);
            c1.add(s4);
            c.addAll(c1);
            //========
            Collection c2=new ArrayList();
            c2.add(s5);
            c2.add(s6);
            c.addAll(c2);
            //========
            
            //移除一个或多个元素
            c.remove(s1);
            c.removeAll(c1);
            
            //查看某个元素是否存在于集合中
            System.out.println(c.contains(s2));
            System.out.println(c.containsAll(c2));
            
            //判断集合是否为空
            System.out.println(c.isEmpty());
            
            //判断集合中有几个元素
            System.out.println(c.size());
            
            //集合转数组 此处不可以用Student[]类型来接收,存入集合的元素都将变成Object类型的
            Object[] objs=c.toArray();
            
            //清空集合
            c.clear();
            
            //迭代遍历
            Iterator it=c.iterator();
            while(it.hasNext()){
                Student s=(Student)it.next();
                System.out.println(s.name+" "+s.age);
            }

    List集合特有的功能

    /*
             * List集合的特有功能:
             * A:添加功能
             *         void add(int index,Object element):在指定位置添加元素
             * B:获取功能
             *         Object get(int index):获取指定位置的元素
             * C:列表迭代器
             *         ListIterator listIterator():List集合特有的迭代器
             * D:删除功能
             *         Object remove(int index):根据索引删除元素,返回被删除的元素
             * E:修改功能
             *         Object set(int index,Object element):根据索引修改元素,返回被修饰的元素
             */
            Student s1=new Student("aaa",15);
            Student s2=new Student("bbb",16);
            Student s3=new Student("ccc",17);
            Student s4=new Student("ddd",18);
            Student s5=new Student("eee",19);
            Student s6=new Student("fff",20);
            List list=new ArrayList();
            list.add(s1);
            list.add(s2);
            
            //在指定位置添加元素,位置可以是0 1 2,否则会报IndexOutOfBoundsException越界异常
            list.add(0,s3);
            list.add(3,s4);
            
            //获取到指定位置的元素
            Student s=(Student)list.get(2);
            System.out.println(s.name+" "+s.age);
            
            //删除指定索引的元素
            list.remove(0);
            
            //设置指定位置的元素
            list.set(0, s5);
            
            System.out.println("-----------------");
            //其实这里可以通过ListIterator实现遍历
            //而且ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以一般无意义,不使用
            Iterator it=list.iterator();
            while(it.hasNext()){
                Student ss=(Student)it.next();
                System.out.println(ss.name+" "+ss.age);
            }
            /*
             * 问题?
             *         我有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
             * 
             * ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 
             * 产生的原因:
             *         迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
             *         其实这个问题描述的是:迭代器遍历元素的时候,通过集合是不能修改元素的。
             * 如何解决呢?
             *         A:迭代器迭代元素,迭代器修改元素
             *             元素是跟在刚才迭代的元素后面的。
             *         B:集合遍历元素,集合修改元素(普通for)
             *             元素在最后添加的。
             */
            List list=new ArrayList();
            list.add("hello");
            list.add("world");
            list.add("java");
            for (int x = 0; x < list.size(); x++) {
                String s = (String) list.get(x);
                if ("world".equals(s)) {
                    list.add("javaee");
                }
            }
            System.out.println("list:" + list);

    ArrayList里面没有什么特有的功能

    LinkedList特有的功能

      A:添加功能
        public void addFirst(Object e)
        public void addLast(Object e)
      B:获取功能
        public Object getFirst()
        public Obejct getLast()
      C:删除功能
        public Object removeFirst()
        public Object removeLast()

    数组中必须存放同种类型的元素,那想要约束一个集合必须存储同种类型的元素就要用到泛型,集合中的泛型只能是引用类型

    泛型可以把运行时的错误提前到编译期,同时避免了强制从Object到特定类型的类型转换,同时在Eclipse中也没有黄色的警告线了

    ArrayList<String> array = new ArrayList<String>();
    array.add("hello");
    array.add("world");
    array.add("java");
    Iterator<String> it = array.iterator();
    while (it.hasNext()) {
        String s = it.next();//不必强转
        System.out.println(s);
    }

    泛型类

    如下代码:早期的时候,我们使用Object来代表任意的类型。向上转型是没有任何问题的,但是在向下转型的时候其实隐含了类型转换的问题。也就是说这样的程序其实并不是安全的。

    public class ObjectTool {
        private Object obj;
    
        public Object getObj() {
            return obj;
        }
    
        public void setObj(Object obj) { // Object obj = new Integer(30);
            this.obj = obj;
        }
    }
    public class ObjectToolDemo {
        public static void main(String[] args) {
            ObjectTool ot = new ObjectTool();
    
            // 正常使用
            ot.setObj(new Integer(27));
            Integer i = (Integer) ot.getObj();
            System.out.println("年龄是:" + i);
    
            ot.setObj(new String("林青霞"));
            String s = (String) ot.getObj();
            System.out.println("姓名是:" + s);
    
            System.out.println("---------");
            ot.setObj(new Integer(30));
            // ClassCastException 出异常了
            String ss = (String) ot.getObj();
            System.out.println("姓名是:" + ss);
        }
    }

    所以Java在JDK5后引入了泛型,提高程序的安全性:

    public class ObjectTool<T> {
        private T obj;
    
        public T getObj() {
            return obj;
        }
    
        public void setObj(T obj) {
            this.obj = obj;
        }
    }
    public class ObjectToolDemo {
        public static void main(String[] args) {
            ObjectTool<String> ot = new ObjectTool<String>();
            // ot.setObj(new Integer(27)); //这个时候编译期间就过不去
            ot.setObj(new String("林青霞"));
            String s = ot.getObj();
            System.out.println("姓名是:" + s);
    
            ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
            // ot2.setObj(new String("风清扬"));//这个时候编译期间就过不去
            ot2.setObj(new Integer(27));
            Integer i = ot2.getObj();
            System.out.println("年龄是:" + i);
        }
    }

    泛型还可以用于方法和接口

    泛型方法

    上面的泛型类有一个很不好的地方就是setObj的参数的类型只能是和ObjectTool里面的泛型类一样的类的类型,这样就很不灵活,所以产生了泛型方法

    public class ObjectTool {
        public <T> void show(T t) {
            System.out.println(t);
        }
    }
    public class ObjectToolDemo {
        public static void main(String[] args) {
            // 定义泛型方法后
            ObjectTool ot = new ObjectTool();
            ot.show("hello");
            ot.show(100);
            ot.show(true);
        }
    }

    ObjectTool类本身还可以有泛型,例如ObjectTool<Boolean>,ObjectTool本身的泛型类型和它里面的成员方法的泛型类型没有任何关系

    泛型接口

    public interface Inter<T> {
        public abstract void show(T t);
    }
    //第一种情况:已经知道该是什么类型的了,用的很少
    public class InterImpl implements Inter<String> {
        public void show(String t) {
            System.out.println(t);
        }
    }
    //第二种情况:还不知道是什么类型的,用的很多
    public class InterImpl<T> implements Inter<T> {
        public void show(T t) {
            System.out.println(t);
        }
    }
    public class InterDemo {
        public static void main(String[] args) {
            // 第一种情况的测试
            Inter<String> i = new InterImpl();
            i.show("hello");
        
            // 第二种情况的测试
            Inter<Integer> ii = new InterImpl<Integer>();
            ii.show(100);
    
            Inter<String> iii = new InterImpl<String>();
            iii.show("hello");
        }
    }

    泛型通配符

    /*
     * 泛型高级(通配符)
     * ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
     * ? extends E:向下限定,E及其子类
     * ? super E:向上限定,E极其父类
     */
    public class GenericDemo {
        public static void main(String[] args) {
            // 泛型如果明确的写的时候,前后必须一致
            Collection<Object> c1 = new ArrayList<Object>();
            // Collection<Object> c2 = new ArrayList<Animal>();
            // Collection<Object> c3 = new ArrayList<Dog>();
            // Collection<Object> c4 = new ArrayList<Cat>();
    
            // ?表示任意的类型都是可以的
            Collection<?> c5 = new ArrayList<Object>();
            Collection<?> c6 = new ArrayList<Animal>();
            Collection<?> c7 = new ArrayList<Dog>();
            Collection<?> c8 = new ArrayList<Cat>();
    
            // ? extends E:向下限定,E及其子类
            // Collection<? extends Animal> c9 = new ArrayList<Object>();
            Collection<? extends Animal> c10 = new ArrayList<Animal>();
            Collection<? extends Animal> c11 = new ArrayList<Dog>();
            Collection<? extends Animal> c12 = new ArrayList<Cat>();
    
            // ? super E:向上限定,E极其父类
            Collection<? super Animal> c13 = new ArrayList<Object>();
            Collection<? super Animal> c14 = new ArrayList<Animal>();
            // Collection<? super Animal> c15 = new ArrayList<Dog>();
            // Collection<? super Animal> c16 = new ArrayList<Cat>();
        }
    }
    
    class Animal {
    }
    
    class Dog extends Animal {
    }
    
    class Cat extends Animal {
    }

    JDK1.5新特性——可变参

    /*
     * 可变参数:定义方法的时候不知道该定义多少个参数
     * 格式:
     *         修饰符 返回值类型 方法名(数据类型…  变量名){
     * 
     *         }
     * 
     *         注意:
     *             这里的变量其实是一个数组
     *             如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
     */
    public ArgsTest{
        public static void main(String args[]){
            int r=sum(10,20,30);
            System.out.println(r);
        }
        public static int sum(int... a){
            int sum=0;
            for(int i:a){
                sum+=a[i];
            }
            return sum;
        }
    }

    Arrays.asList传入可变参作为参数

    /*
     * public static <T> List<T> asList(T... a):把数组转成集合
     * 
     * 注意事项:
     *         虽然可以把数组转成集合,但是集合的长度不能改变。
     */
    public class ArraysDemo {
        public static void main(String[] args) {
            // 定义一个数组
            // String[] strArray = { "hello", "world", "java" };
            // List<String> list = Arrays.asList(strArray);
    
            List<String> list = Arrays.asList("hello", "world", "java");
            // UnsupportedOperationException
            // list.add("javaee");
            // UnsupportedOperationException
            // list.remove(1);
            list.set(1, "javaee");
    
            for (String s : list) {
                System.out.println(s);
            }
        }
    }

    以上是List集合的相关类及其方法的总结,List集合是有序的,即存和取的顺序是一致的,List集合里面的元素可以重复

    Set集合是无序的,存和取的顺序不一致,而且取的时候不保证顺序永久不变,但是作为集合来说,它肯定有自己的存储顺序,Set集合里面的元素是唯一的

    Set的一个很重要的实现类是HashSet

    此外还有LinkedHashSet,该类的底层数据结构由哈希表和链表组成,哈希表保证元素的唯一性,链表保证元素有顺序,即存进去和取出来的元素顺序相同

    Collection和Collections的区别

    Collection:是单列集合的顶层接口,有子接口List和Set。
    Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法

    要知道的方法
    public static <T> void sort(List<T> list):排序 默认情况下是自然顺序。
    public static <T> int binarySearch(List<?> list,T key):二分查找
    public static <T> T max(Collection<?> coll):最大值
    public static void reverse(List<?> list):反转
    public static void shuffle(List<?> list):随机置换

    同Collection并列的还有另外一个顶层集合接口——Map

    Map中存储的是键值对,类似js里面的json

    Map<String,String> hm = new HashMap<String,String>();
    
    hm.put("it002","hello");
    hm.put("it003","world");
    hm.put("it001","java");
    
    //方式1 键找值 set是键的集合
    Set<String> set = hm.keySet();
    for(String key : set) {
        String value = hm.get(key);
        System.out.println(key+"---"+value);
    }
    
    //方式2 键值对对象找键和值 set2是键值对的集合
    Set<Map.Entry<String,String>> set2 = hm.entrySet();
    for(Map.Entry<String,String> me : set2) {
        String key = me.getKey();
        String value = me.getValue();
        System.out.println(key+"---"+value);
    }
  • 相关阅读:
    【解决】Linux Tomcat启动慢Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [236,325] milliseconds
    初学java总结
    第8周课程总结&实验报告6
    第9周总结&实验报告7
    实验报告5&第七周课程总结
    第五周课程总结、实验报告三
    第六周总结&实验报告四
    使用REST接口获取GeoServer中的图层列表
    网上最流行的FLASH焦点图文幻灯片(focus.swf改进版),可支持jpg/gif/png/swf文件(转载)
    使用PostgreSQL的bytea字段存读取文件及读取出错问题处理
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/5010876.html
Copyright © 2011-2022 走看看