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());
            }
        }
    
    }

  • 相关阅读:
    webapi 获取json数据
    js的匿名函数与自定义函数
    深入理解计算机系统 第八章 异常控制流(2)
    深入理解计算机系统 第八章 异常控制流(1)
    深入理解计算机系统 第三章 程序的机器级表示(2)
    深入理解计算机系统 第三章 程序的机器级表示(1)
    深入理解计算机系统 第二章 信息的表示和处理(2)
    深入理解计算机系统 第二章 信息的表示和处理(1)
    深入理解计算机系统第一章,计算机系统漫游
    Leetcode练习(Python):第292题:Nim 游戏:你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/10946311.html
Copyright © 2011-2022 走看看