zoukankan      html  css  js  c++  java
  • 06java进阶——集合框架(list和泛型)

    1.ArrayList

    ArrayList集合是程序中最常见的一种集合,它属于引用数据类型(类)。在ArrayList内部封装了一个长度可变的数组,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。

    1.1ArrayList的创建

    导包:import java.util.ArrayList;

    创建对象:与其他普通的引用数据类型创建方式完全相同,但是要指定容器中存储的数据类型:

    ArrayList<要存储元素的数据类型> 变量名 = new ArrayList<要存储元素的数据类型>();

    •  集合中存储的元素,只能为<>括号中指定的数据类型元素;
    • “<要存储元素的数据类型>”中的数据类型必须是引用数据类型,不能是基本数据类型;

    下面给出8种基本数据类型所对应的引用数据类型表示形式:

    我们通过举几个例子,来明确集合的创建方式:

    • 存储String类型的元素
    ArrayList<String> list = new ArrayList<String>();
    • 存储int类型的数据
    ArrayList<Integer> list = new ArrayList<Integer>();
    • 存储Phone类型的数据
      ArrayList<Phone> list = new ArrayList<Phone>();

    1.2常用的方法

    package cn.jxufe.java.chapter6;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class TestArrayList01 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            // 创建ArrayList集合
            ArrayList<String> list1 = new ArrayList<String>();// 第二个可以省略
            // 向集合中添加元素
    
            list1.add("stu1");
            list1.add("stu2");
            list1.add("stu3");
            list1.add("stu4");
            // 获取集合中元素的个数
            // 取出并打印指定位置的元素
            System.out.println("第2个元素是:" + list1.get(1));
            System.out.println("list1中的元素为:");
            System.out.println(list1);
            System.out.println("去除索引值为2的元素后,list中的元素为");
            list1.remove(2);
            System.out.println(list1);
            System.out.println("在索引值为1的元素处添加一个student元素:");
            list1.add(1, "student");
            System.out.println(list1);
            System.out.println("把索引位置为3的元素置为good:");
            list1.set(3, "good");
            System.out.println(list1);
            // 集合的遍历
            System.out.println("集合的遍历方法1:");
            for (String e : list1) {
                System.out.print(e + "  ");
            }
            System.out.println("\n集合的遍历方法2: ");
            for (int i = 0; i < list1.size(); i++) {
                System.out.print(list1.get(i) + "  ");
            }
            System.out.println("\nlist1是否为空:");
            System.out.println(list1.isEmpty());
            System.out.println("list1是否包涵good:");
            System.out.println(list1.contains("good"));
    
            ArrayList<String> list2 = new ArrayList<>();
            list2.add("stu1");
            list2.add("stu2");
            System.out.println("list2中的元素为:");
            System.out.println(list2);
            System.out.println("从list1中移除list2中的全部元素");
            list1.removeAll(list2);// 获得两个集合元素的差集
            System.out.println(list1);
            System.out.println("list1添加list2中的全部元素");
            list1.addAll(list2);// 获得两个集合元素的并集
            System.out.println(list1);
    
            List<String> list3 = new ArrayList<String>();
            list3.add("第一个元素"); // 向列表中添加数据
            list3.add("第二个元素"); // 向列表中添加数据
            list3.add("第三个元素"); // 向列表中添加数据
            List<String> list4 = new ArrayList<String>();
            list4.add("第一个元素"); // 向列表中添加数据
            list4.add("第三个元素"); // 向列表中添加数据
            System.out.println("--------测试retainAll的使用------------:");
            boolean ret = list3.retainAll(list4); // 获得两集合相交的元素
            System.out.println(ret);
            System.out.println(list3);
    
            // 创建迭代器
            Iterator<String> it = list3.iterator();
            // 循环遍历迭代器
            System.out.println("循环遍历迭代器:");
            while (it.hasNext()) {
                System.out.println(it.next()); // 输出集合中元素
            }
    
            ArrayList<String> list5 = new ArrayList<>();
            ArrayList<String> list6 = new ArrayList<>();
            list5.add("a");
            list5.add("b");
            list5.add("c");
            list6.add("b");
            list6.add("c");
            list6.add("d");
            list5.retainAll(list6);// 获得两集合相交的元素
            System.out.println(list5);
        }
    }

    查看ArrayList类发现它继承了抽象类AbstractList同时实现接口List,而List接口又继承了Collection接口。Collection接口为最顶层集合接口了。

     源代码:
          interface List extends Collection {
          }
          public class ArrayList extends AbstractList implements List{
          }
        

    集合继承体系
    这说明我们在使用ArrayList类时,该类已经把所有抽象方法进行了重写。那么,实现Collection接口的所有子类都会进行方法重写。

    • Collecton接口常用的子接口有:List接口、Set接口
    • List接口常用的子类有:ArrayList类、LinkedList类
    • Set接口常用的子类有:HashSet类、LinkedHashSet类

    2.迭代器

      java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。
    Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

    package cn.jxufe.java.chapter6;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class TestIterator03 {
        /*
         * 集合中的迭代器: 获取集合中元素方式 接口 Iterator : 两个抽象方法 boolean hasNext()
         * 判断集合中还有没有可以被取出的元素,如果有返回true next() 取出集合中的下一个元素
         * 
         * Iterator接口,找实现类. Collection接口定义方法 Iterator iterator() ArrayList
         * 重写方法iterator(),返回了Iterator接口的实现类的对象 使用ArrayList集合的对象 Iterator
         * it=array.iterator(),运行结果就是Iterator接口的实现类的对象 it是接口的实现类对象,调用方法 hasNext 和 next
         * 集合元素迭代
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Collection<String> coll = new ArrayList<String>();
            coll.add("abc1");
            coll.add("abc2");
            coll.add("abc3");
            coll.add("abc4");
            // 迭代器,对集合ArrayList中的元素进行取出
    
            // 调用集合的方法iterator()获取出,Iterator接口的实现类的对象
            Iterator<String> it = coll.iterator();
            // 接口实现类对象,调用方法hasNext()判断集合中是否有元素
            // boolean b = it.hasNext();
            // System.out.println(b);
            // 接口的实现类对象,调用方法next()取出集合中的元素
            // String s = it.next();
            // System.out.println(s);
    
            // 迭代是反复内容,使用循环实现,循环的条件,集合中没元素, hasNext()返回了false
            while (it.hasNext()) {
                String s = it.next();
                System.out.println(s);
            }
            System.out.println();
            // for循环的方式进行遍历,for没有while好理解,但是节约点内存,因为while的it是在main函数中建立的,for的it是在for中建立的
            for (Iterator<String> it2 = coll.iterator(); it2.hasNext();) {
                System.out.println(it2.next());
            }
        }
    
    }

    3.集合迭代中的转型

    存储时提升了Object。取出时要使用元素的特有内容,必须向下转型。

    package cn.jxufe.java.chapter6;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class TestCollection04 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Collection coll = new ArrayList();
            coll.add("abc");
            coll.add("aabbcc");
            coll.add("shitcast");
            Iterator it = coll.iterator();
            while (it.hasNext()) {
                // 由于元素被存放进集合后全部被提升为Object类型
                // 当需要使用子类对象特有方法时,需要向下转型
                String str = (String) it.next();
                System.out.println(str.length());
            }
            // 注意:如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常。
        }
    
    }

    4.泛型

    4.1泛型的引入

    在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。比如下面程序:

    package cn.jxufe.java.chapter6;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class TestGeneric05 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            List list = new ArrayList();
            list.add("abc");
            list.add("itcast");
            list.add(5);// 由于集合没有做任何限定,任何类型都可以给其中存放
                        // 相当于:Object obj=new Integer(5);
    
            Iterator it = list.iterator();
            while (it.hasNext()) {
                // 需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
                String str = (String) it.next();// String str=(String)obj;
                                                // 编译时期仅检查语法错误,String是Object的儿子可以向下转型
                                                // 运行时期String str=(String)(new Integer(5))
                                                // String与Integer没有父子关系所以转换失败
                                                // 程序在运行时发生了问题java.lang.ClassCastException
                System.out.println(str.length());
            }
        }
    }

    4.2泛型的定义和使用

     泛型: 指明了集合中存储数据的类型  <数据类型>

    上面已经使用了

    4.3Java中的伪泛型

    泛型只在编译时存在,编译后就被擦除,在编译之前我们就可以限制集合的类型,起到作用
    例如:ArrayList<String> al=new ArrayList<String>();
    编译后:ArrayList al=new ArrayList();

    4.4泛型类

    a:定义格式:

    修饰符 class 类名<代表泛型的变量> {  }
          
          例如,API中的ArrayList集合:
          class ArrayList<E>{ 
               public boolean add(E e){ }
            public E get(int index){  }
          }

     b:使用格式:

    创建对象时,确定泛型的类型
         
          例如,ArrayList<String> list = new ArrayList<String>();
          此时,变量E的值就是String类型
          class ArrayList<String>{ 
            public boolean add(String e){ }
            public String get(int index){  }
          }
         
          例如,ArrayList<Integer> list = new ArrayList<Integer>();
          此时,变量E的值就是Integer类型
          class ArrayList<Integer>{ 
               public boolean add(Integer e){ }
               public Integer get(int index){  }
          }

    package cn.jxufe.java.chapter6;
    
    import java.util.ArrayList;
    
    public class GenericStack07<E> {
    
        ArrayList<E> list = new ArrayList<>();
    
        public int getSize() {
            return list.size();
        }
    
        public E peek() {
            return list.get(getSize() - 1);
        }
    
        public E pop() {
            E o = list.get(getSize() - 1);
            list.remove(getSize() - 1);
            return o;
        }
    
        public boolean isEmpty() {
            return list.isEmpty();
        }
    
        public void push(E e) {
            list.add(e);
        }
    
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "stack: " + list.toString();
        }
    
        public static void main(String[] args) {
            GenericStack07<String> stack1 = new GenericStack07<>();
            stack1.push("good");
            stack1.push("good");
            stack1.push("study");
            System.out.println(stack1);
            
            GenericStack07<Integer> stack2 = new GenericStack07<>();
            stack2.push(123);
            stack2.push(456);
            stack2.push(789);
            System.out.println(stack2);
        }
    }

    4.5泛型的方法

    • a:定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){  }
    • b:泛型方法的使用:
      例如,API中的ArrayList集合中的方法:
          public <T> T[] toArray(T[] a){  } 
          //该方法,用来把集合元素存储到指定数据类型的数组中,返回已存储集合元素的数组
    
          使用格式:调用方法时,确定泛型的类型
      例如:
              ArrayList<String> list = new ArrayList<String>();
              String[] arr = new String[100];
              String[] result = list.toArray(arr);
           此时,变量T的值就是String类型。变量T,可以与定义集合的泛型不同
           public <String> String[] toArray(String[] a){  } 
    
      例如:
              ArrayList<String> list = new ArrayList<String>();
              Integer[] arr = new Integer[100];
              Integer [] result = list.toArray(arr);
          
          此时,变量T的值就是Integer类型。变量T,可以与定义集合的泛型不同
          public <Integer> Integer[] toArray(Integer[] a){  } 

     使用泛型类型来定义泛型方法

    package cn.jxufe.java.chapter6;
    
    public class TestGenericMethod {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Integer[] integers = { 1, 2, 3, 4, 5 };
            String[] strings = { "london", "xuzhou", "nanchang" };
            print(integers);
            print(strings);
        }
    
        public static <E> void print(E[] list) {
            for (E e : list) {
                System.out.print(e + " ");
            }
            System.out.println();
        }
    
    }

    4.6泛型的接口 

    /*
          *  带有泛型的接口
          *  
          *  public interface List <E>{
          *    abstract boolean add(E e);
          *  }
          * 
          *  实现类,先实现接口,不理会泛型
          *  public class ArrayList<E> implements List<E>{
          *  }
          *  调用者 : new ArrayList<String>() 后期创建集合对象的时候,指定数据类型
          *  
          *  
          *  实现类,实现接口的同时,也指定了数据类型
          *  public class XXX implements List<String>{
          *  }
          *  new XXX()
          */

    4.7受限的泛型类型

    可以将泛型指定为另一种类型的子类型,这样的泛型类型称为受限的。

    package cn.jxufe.java.chapter6;
    
    abstract class GeometricObject {
        public abstract double getArea();
    }
    
    class Rectangle extends GeometricObject {
        double length;
        double hight;
    
        public Rectangle(double length, double hight) {
            // TODO Auto-generated constructor stub
            this.length = length;
            this.hight = hight;
        }
    
        public double getArea() {
            return length * hight;
        }
    }
    
    class Circle extends GeometricObject {
        double radius;
    
        public Circle(double radius) {
            // TODO Auto-generated constructor stub
            this.radius = radius;
        }
    
        public double getArea() {
            return 3.14 * radius * radius;
        }
    }
    
    public class TestBoundedType {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Rectangle rectangle = new Rectangle(2, 2);
            Rectangle rectangle2 = new Rectangle(2, 2);
            Circle circle = new Circle(2);
            System.out.println(equalArea(rectangle, circle));
            System.out.println(equalArea(rectangle, rectangle2));
        }
    
        public static <E extends GeometricObject> boolean equalArea(E object1, E object2) {
            return object1.getArea() == object2.getArea();
        }
    
    }

    4.8示例学习:对一个对象数组进行排序

    package cn.jxufe.java.chapter6;
    
    public class TestGenericSort {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Integer[] intArray = { new Integer(2), new Integer(4), new Integer(3) };
            Double[] doubleArray = { new Double(3.4), new Double(1.3), new Double(-22.1) };
            Character[] charArray = { new Character('a'), new Character('c'), new Character('b') };
            String[] stringArray = { "tom", "jack", "blue" };
            sort(intArray);
            sort(doubleArray);
            sort(charArray);
            sort(stringArray);
    
            System.out.println("sorted integer objects:");
            printList(intArray);
            System.out.println("sorted double objects:");
            printList(doubleArray);
            System.out.println("sorted charArray objects:");
            printList(charArray);
            System.out.println("sorted stringArray objects:");
            printList(stringArray);
        }
    
        public static <E extends Comparable<E>> void sort(E[] list) {
            E currentMin;
            int currentMinIndex;
            for (int i = 0; i < list.length - 1; i++) {
                currentMin = list[i];
                currentMinIndex = i;
                for (int j = i + 1; j < list.length; j++) {
                    if (currentMin.compareTo(list[j]) > 0) {
                        currentMin = list[j];
                        currentMinIndex = j;
                    }
                }
                if (currentMinIndex != i) {
                    list[currentMinIndex] = list[i];
                    list[i] = currentMin;
                }
            }
        }
    
        public static void printList(Object[] list) {
            for (int i = 0; i < list.length; i++) {
                System.out.print(list[i] + " ");
            }
            System.out.println();
        }
    
    }

    4.9泛型的好处

    • 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
    • 避免了类型强转的麻烦。

    4.10泛型的通配符

     

    package cn.jxufe.java.chapter6;
    
    public class TestWildCard {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            GenericStack07<Integer> intStack = new GenericStack07<>();
            intStack.push(1);
            intStack.push(2);
            intStack.push(-1);
            
            System.out.println("the max number is " + max(intStack));//编译会报错,因为intStack不是GenericStack<Number>的实例
        }
    
        public static double max(GenericStack07<Number> stack) {
            double max = stack.pop().doubleValue();
            while (!stack.isEmpty()) {
                double value = stack.pop().doubleValue();
                if (value > max)
                    max = value;
            }
            return max;
        }
    
    }

    package cn.jxufe.java.chapter6;
    
    public class TestWildCard {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            GenericStack07<Integer> intStack = new GenericStack07<>();
            intStack.push(1);
            intStack.push(2);
            intStack.push(-1);
            
            System.out.println("the max number is " + max(intStack));//编译会报错,因为intStack不是GenericStack<Number>的实例
        }
    
        public static double max(GenericStack07<? extends Number> stack) {
            double max = stack.pop().doubleValue();
            while (!stack.isEmpty()) {
                double value = stack.pop().doubleValue();
                if (value > max)
                    max = value;
            }
            return max;
        }
    
    }

    package cn.jxufe.java.chapter6;
    
    public class TestAnyWild {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            GenericStack07<Integer> intStack = new GenericStack07<>();
            intStack.push(1);
            intStack.push(2);
            intStack.push(-2);
            print(intStack);
            
            GenericStack07<String> stringStack = new GenericStack07<>();
            stringStack.push("zhangSan");
            stringStack.push("zhaoSi");
            stringStack.push("wangWu");
            print(stringStack);
            
    
        }
    
        public static void print(GenericStack07<?> stack) {
            while (!stack.isEmpty()) {
                System.out.print(stack.pop() + " ");
            }
            System.out.println();
        }
    
    }

    package cn.jxufe.java.chapter6;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Iterator;
    
    public class TestWildcard06 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            ArrayList<String> array = new ArrayList<String>();
    
            HashSet<Integer> set = new HashSet<Integer>();
    
            array.add("123");
            array.add("456");
    
            set.add(789);
            set.add(890);
    
            iterator(array);
            iterator(set);
        }
    
        /*
         * 定义方法,可以同时迭代2个集合 参数: 怎么实现 , 不能写ArrayList,也不能写HashSet 参数: 或者共同实现的接口
         * 泛型的通配,匹配所有的数据类型 ?
         */
        public static void iterator(Collection<?> coll) {
            Iterator<?> it = coll.iterator();
            while (it.hasNext()) {
                // it.next()获取的对象,什么类型
                System.out.println(it.next());
            }
        }
    }

     

    package cn.jxufe.java.chapter6;
    
    public class TestSuperWildChard {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            GenericStack07<String> stack1 = new GenericStack07<>();
            GenericStack07<Object> stack2 = new GenericStack07<>();
            stack2.push("java");
            stack2.push(2);
            stack1.push("sun");
            add(stack1, stack2);
            TestAnyWild12.print(stack2);
        }
    
        public static <T> void add(GenericStack07<T> stack1, GenericStack07<? super T> stack2) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
    
    }

  • 相关阅读:
    python 写入txt的新方法
    python 对excel进行截图
    python 关于excel弹窗——请注意,您的文档的部分内容可能包含了文档检查器无法删除的个人信息解决方法
    python win32com 读取带密码的excel
    移动硬盘——显示盘符但打不开
    python datetime和time的一些疑惑解答 及 获取上年同期、上月等日期
    pyinstaller 打包exe程序读不到配置文件No such file
    Python之——爱心代码参与情人节
    《易学设计模式》-笔记
    "高级"数据库小结
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/10946311.html
Copyright © 2011-2022 走看看