传智播客-Java学习笔记day16

1.ArrayList存储自定义对象并遍历
public static void main(String[] args) {
        // 创建集合对象
         ArrayList array = new ArrayList();
 
        // 创建学生对象
        Student s1 = new Student("武松", 30);
        Student s2 = new Student("鲁智深", 40);
        Student s3 = new Student("林冲", 36);
        Student s4 = new Student("杨志", 38);
 
        // 添加元素
        array.add(s1);
        array.add(s2);
        array.add(s3);
        array.add(s4);
 
        // 遍历
        Iterator it =  array.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.getName() + "---" + s.getAge());
        }
 
        System.out.println("----------------");
 
        for (int x = 0; x <  array.size(); x++) {
          
            Student s = (Student)  array.get(x);
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }
 
2.Vector
Vector的特有功能:
 * 1:添加功能
 *         public void addElement(Object obj)        --    被后来的add()替代
 * 2:获取功能
 *         public Object elementAt(int index)        --  被后来的get()替代
 *         public  Enumeration elements()            --   被后来的Iterator iterator()替代
 *                 boolean hasMoreElements()                被后来的hasNext()替代
 *                 Object nextElement()                   被后来的next()替代
 * 
 * 附:JDK升级的原因:
 *         A:安全
 *         B:效率
 *         C:简化书写
 
public static void main(String[] args) {
        // 创建集合对象
        Vector v = new Vector();
 
        // 添加功能
        v.addElement("hello");
        v.addElement("world");
        v.addElement("java");
 
        // 遍历
        for (int x = 0; x < v.size(); x++) {
            String s = (String) v.elementAt(x);
            System.out.println(s);
        }
 
        System.out.println("------------------");
 
         Enumeration en = v. elements(); // 返回的是实现类的对象
        while (en. hasMoreElements()) {
            String s = (String) en. nextElement();
            System.out.println(s);
        }
    }
3.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()

 

 

4.一个案例
ArrayList去除集合中字符串的重复值(字符串的内容相同)
思路
 
分析:
 *         A:创建集合对象
 *         B:添加多个字符串元素(包含内容相同的)
 *         C:创建新集合
 *         D:遍历旧集合,获取得到每一个元素
 *         E: 拿这个元素到新集合去找,看有没有
 *             有:不搭理它
 *             没有:就添加到新集合
 *         F:遍历新集合
 
public static void main(String[] args) {
        // 创建集合对象
        ArrayList array = new ArrayList();
 
        // 添加多个字符串元素(包含内容相同的)
        array.add("hello");
        array.add("world");
        array.add("java");
        array.add("world");
        array.add("java");
        array.add("world");
        array.add("world");
        array.add("world");
        array.add("world");
        array.add("java");
        array.add("world");
 
        // 创建新集合
        ArrayList newArray = new ArrayList();
 
        // 遍历旧集合,获取得到每一个元素
        Iterator it = array.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
 
            // 拿这个元素到新集合去找,看有没有
            if (!newArray. contains(s)) {
                newArray.add(s);
            }
        }
 
        // 遍历新集合
        for (int x = 0; x < newArray.size(); x++) {
            String s = (String) newArray.get(x);
            System.out.println(s);
        }
    }
 
这个案例,注意contains(s)的使用,很容易忽(wang)略(ji)这个功能!!。
5.上一个案例的另外一种思路(有点复杂,理解一下就行,常用上一中方法)
需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
 要求: 不能创建新的集合,就在以前的集合上做。
public static void main(String[] args) {
        // 创建集合对象
        ArrayList array = new ArrayList();
 
        // 添加多个字符串元素(包含内容相同的)
        array.add("hello");
        array.add("world");
        array.add("java");
        array.add("world");
        array.add("java");
        array.add("world");
        array.add("world");
        array.add("world");
        array.add("world");
        array.add("java");
        array.add("world");
 
        //  由选择排序思想引入,我们就可以通过这种思想做这个题目
        // 拿0索引的依次和后面的比较,有就把后的干掉
        // 同理,拿1索引...
        for (int x = 0; x < array.size() - 1; x++) {
            for (int y = x + 1; y < array.size(); y++) {
                if (array.get(x).equals(array.get(y))) {
                    array.remove(y);
                     y--;
                }
            }
        }
 
        // 遍历集合
        Iterator it = array.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println(s);
        }
    }
 
下面解析一下y--的来源,为什么要有y--,
首先,没有y--,程序结果不对
 
接着,通过设置断点debug发现
 
最后,通过添加y--解决
 
6.另一个案例
需求:去除集合中 自定义对象的重复值(对象的成员变量值都相同)
自定义对象可以为学生类
 
我们按照和字符串一样的操作,发现出问题了。
 
public static void main(String[] args) {
        // 创建集合对象
        ArrayList array = new ArrayList();
 
        // 创建学生对象
        Student s1 = new Student("林青霞", 27);
        Student s2 = new Student("林志玲", 40);
        Student s3 = new Student("凤姐", 35);
        Student s4 = new Student("芙蓉姐姐", 18);
        Student s5 = new Student("翠花", 16);
        Student s6 = new Student("林青霞", 27);
        Student s7 = new Student("林青霞", 18);
 
        // 添加元素
        array.add(s1);
        array.add(s2);
        array.add(s3);
        array.add(s4);
        array.add(s5);
        array.add(s6);
        array.add(s7);
 
        // 创建新集合
        ArrayList newArray = new ArrayList();
 
        // 遍历旧集合,获取得到每一个元素
        Iterator it = array.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
 
            // 拿这个元素到新集合去找,看有没有
             if (!newArray.contains(s)) {
                newArray.add(s);
            }
        }
 
        // 遍历新集合
        for (int x = 0; x < newArray.size(); x++) {
            Student s = (Student) newArray.get(x);
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }

 

 

 

为什么呢?
       我们必须思考哪里会出问题?
          通过简单的分析,我们知道问题出现在了判断上。
          而这个判断功能是集合自己提供的,所以我们如果想很清楚的知道它是如何判断的,就应该去看源码。
------有问题,查源码

 

 

 

 

通过查源码发现 
contains()方法的底层依赖的是equals()方法。
  而我们的学生类中没有equals()方法,这个时候,默认使用的是它父亲Object的equals()方法
  Object()的equals()默认比较的是地址值,所以,它们进去了。因为new的东西,地址值都不同。
  按照我们自己的需求,比较成员变量的值,重写equals()即可。(在Student类中重写)
  运用代码自动生成即可。
 
7.请用LinkedList模拟栈数据结构的集合,并测试
 
题目的意思是:
       你自己的定义一个集合类,在这个集合类内部可以使用LinkedList模拟。
MyStack类
MySatckTest
 
8.泛型的引入,概述
有疑问,反编译(xJad)
 
编译不出问题,但是运行就报错了
8.泛型概述和基本使用
回想一下,我们的数组
          String[] strArray = new String[3];
          strArray[0] = "hello";
          strArray[1] = "world";
          strArray[2] = 10;
  集合也模仿着数组的这种做法, 在创建对象的时候明确元素的数据类型。这样就不会在有问题了。
  而这种技术被称为:泛型。
  
  泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。
  格式:
          <数据类型>
           此处的数据类型只能是引用类型。
  好处:
          A: 把运行时期的问题提前到了编译期间
          B: 避免了强制类型转换
          C:优化了程序设计,解决了黄色警告线
 
public static void main(String[] args) {
        // 创建
        ArrayList  array = new ArrayList ();
 
        // 添加元素
        array.add("hello");
        array.add("world");
        array.add("java");
 
        // 遍历
        Iterator  it = array.iterator();
        while (it.hasNext()) {
            // ClassCastException
             // String s = (String) it.next();
             String s = it.next();
            System.out.println(s);
        }
    }
 
2.泛型在哪些地方使用呢?
看API,如果类,接口,抽象类后面跟的有就说要使用泛型。 一般来说就是在集合中使用
 
以下用ArrayList存储字符串元素,并遍历。用泛型改进代码
public static void main(String[] args) {
        ArrayList array = new ArrayList();
 
        array.add("hello");
        array.add("world");
        array.add("java");
 
        Iterator it = array.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }
        System.out.println("-----------------");
 
        for (int x = 0; x < array.size(); x++) {
             String s = array.get(x);
            System.out.println(s);
        }
    }
 
3 .JDK7的新特性--------泛型推断
 创建集合对象
   ArrayList array = new ArrayList();//一般情况下
   JDK7的新特性: 泛型推断
          ArrayList array = new ArrayList<>();
         但是不建议这样使用。
        ArrayList array = new ArrayList();//还是这样写
 
4.泛型类:把泛型定义在类上
举例
=============================================
ObjectTool.java
 
public class ObjectTool  {
    private  T obj;
 
    public  getObj() {
        return obj;
    }
 
    public void setObj( T obj) {
        this.obj = obj;
    }
}
====================================================
ObjectToolDemo.java
 
 
public class ObjectToolDemo {
    public static void main(String[] args) {
        ObjectTool  ot = new ObjectTool ();
        // ot.setObj(new Integer(27)); //这个时候编译期间就过不去
        ot.setObj(new String("林青霞"));
        String s = ot.getObj();
        System.out.println("姓名是:" + s);
 
        ObjectTool  ot2 = new ObjectTool ();
        // ot2.setObj(new String("风清扬"));//这个时候编译期间就过不去
        ot2.setObj(new Integer(27));
        Integer i = ot2.getObj();
        System.out.println("年龄是:" + i);
    }
}
5. 泛型方法:把泛型定义在方法上(这个时候与泛型类无关!)
原始做法
============================
ObjectTool.java
public class ObjectTool  {
 
    public void show( T t) {
        System.out.println(t);
    }
 }
============================
ObjectToolDemo.java
 
 ObjectTool ot = new ObjectTool ();
        ot.show("hello");
       
        ObjectTool ot2 = new ObjectTool ();
        ot2.show(100);
        
        ObjectTool ot3 = new ObjectTool ();
       ot3.show(true);
 
        // 如果还听得懂,那就说明泛型类是没有问题的
        // 但是呢,谁说了我的方法一定要和类的类型的一致呢?
        // 我要是类上没有泛型的话,方法还能不能接收任意类型的参数了呢?
 
 
 
改进(不定义泛型类,但定义了一个普通类的背后定义一个泛型方法)
ObjectTool.java
public class ObjectTool {
    public   void show( T t) {
        System.out.println(t);
    }
}
 
// 定义泛型方法后 ObjectToolDemo.java
 
        ObjectTool ot = new ObjectTool();
        ot.show("hello");
        ot.show(100);
        ot.show(true);
 
6.泛型接口:把泛型定义在接口上
================================================
Inter.java(定义一个接口,而且是泛型接口)
public interface Inter {
    public abstract void show(T t);
}
================================================
InterImpl.java(用一个类去实现上面的泛型接口)
//实现类在实现接口的时候
//第一种情况:已经知道该是什么类型的了(用得比较少)
 
//public class  InterImpl implements  Inter {
//
//    @Override
//    public void show( String t) {
//        System.out.println(t);
//    }
// }
 
//第二种情况:还不知道是什么类型的( 这种情况最常见,推荐使用,说白了,就是用泛型类实现泛型接口)
public class  InterImpl implements  Inter {
 
    @Override
    public void show( T t) {
        System.out.println(t);
    }
}
=================================
InterDemo.java(测试类)
public static void main(String[] args) {
        // 第一种情况的测试
        // Inter i = new InterImpl();// 只能是String,否则会报错
        // i.show("hello");
 
        // // 第二种情况的测试
        Inter i = new InterImpl();
        i.show("hello");
 
        Inter ii = new InterImpl();
        ii.show(100);
    }
7.泛型高级之通配符
泛型高级(通配符)
 ?: 任意类型,如果没有明确,那么就是Object以及任意的Java类了
 ? extends E:向下限定,E及 其子类
 ? super E:向上限定,E及 其父类
 
背景
class Animal {
}
 
class Dog extends Animal {
}
 
class Cat extends Animal {
}
 
泛型如果明确的写的时候,前后必须一致

 

 

?表示任意的类型都是可以的

? extends E:向下限定,E及其子类

? super E:向上限定,E极其父类

(留意以上截图哪些行报错了)

 

8.JDK5的新特性----增强for
JDK5的新特性:自动拆装箱,泛型,增强for,静态导入,可变参数,枚举
  
  增强for:是for循环的一种。
  
  格式:
           for(元素数据类型 变量 : 数组或者Collection集合) {
             使用变量即可,该变量就是元素
        }
  
  好处: 简化了数组和 集合的遍历。
 
弊端: 增强for的目标不能为null。
 *如何解决呢? 对增强for的目标先进行不为null的判断然后再使用
==========================================
public static void main(String[] args) {
        // 定义一个 int数组
        int[] arr = { 1, 2, 3, 4, 5 };
        for (int x = 0; x < arr.length; x++) {
            System.out.println(arr[x]);
        }
        System.out.println("---------------");
        // 增强for
        for (int x : arr) {
            System.out.println(x);
        }
        System.out.println("---------------");
        // 定义一个 字符串数组
        String[] strArray = { "林青霞", "风清扬", "东方不败", "刘意" };
        // 增强for
        for (String s : strArray) {
            System.out.println(s);
        }
        System.out.println("---------------");
        //  定义一个集合(重点留意这个遍历的简化)
        ArrayList array = new ArrayList();
        array.add("hello");
        array.add("world");
        array.add("java");
        // 增强for
        for ( String s : array) {
            System.out.println(s);
        }
        System.out.println("---------------");
    }
==============================================================
弊端: 增强for的目标不能为null。如下面所示
  List list =  null;
        //  NullPointerException
        // 这个s是我们从list里面获取出来的,在 获取前,它肯定还要做一个 判断
        // 说白了,这就是迭代器的功能
    //又要获取又要判断,所以抛出异常

 

 

//改进
         if (list != null) { //改进后,加一个判断
            for (String s : list) {
                System.out.println(s);
            }
        }
还有一个值得注意的问题

增强for其实就是(用来替代)迭代器
迭代器遍历集合,集合修改集合会产生 并发修改异常。换句话说,增强for就是替代了迭代器(的作用)
详见以下这个例子
 // 增强for其实是用来替代迭代器的
        // ConcurrentModificationException
        // for (String s : array) {
        // if ("world".equals(s)) {
        // array.add("javaee");
        // }
        // }
        // System.out.println("array:" + array);

 

 
9.JDK5的新特性-----静态导入(意义不大,能看懂即可)
 
*静态导入的注意事项:
         A: 方法必须是静态的
       B:如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。
 
10.使用Eclipse快速制作方法
 
 
或者选中a + b来做方法也可以
 
11.JDK5的新特性-----可变参数
可变参数:定义方法的时候不知道该定义多少个参数
  格式:
          修饰符 返回值类型 方法名( 数据类型…  变量名){
 
          }
  
          注意:
              这里的 变量其实是一个数组
              如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个(也就是说,可以是
                method(int a, int...b),但不可以是method(int...b,int a) 。)
 
public static void main(String[] args) {
        // 2个数据求和
        int a = 10;
        int b = 20;
        int result = sum(a, b);
        System.out.println("result:" + result);
 
        // 3个数据的求和
        int c = 30;
        result = sum(a, b, c);
        System.out.println("result:" + result);
 
        // 4个数据的求和
        int d = 30;
        result = sum(a, b, c, d);
        System.out.println("result:" + result);
 
       需求:我要写一个求和的功能,到底是几个数据求和呢,我不太清楚,但是我知道在调用的时候我肯定就知道了
        为了解决这个问题,Java就提供了一个东西:可变参数
        result = sum(a, b, c, d, 40);
        System.out.println("result:" + result);
 
         result = sum(a, b, c, d, 40, 50);
        System.out.println("result:" + result);
    }
 
    public static int sum (int... a) {
        // System.out.println(a);
        //return 0;
 
        int s = 0;
        //在这里,其实 a是一个数组
         for(int x : a){
            s +=x;
        }
 
        return  s;
    }
通过反编译发现,其实还是数组
 
 12.Arrays工具类的asList()方法(接收 可变参数)
 public static  List asList( T... a):把数组转成集合
注释:第一个表示这是一个泛型方法名叫asList
            第二个表示返回值是一个泛型接口---List
public static void main(String[] args) {
        // 定义一个数组
        // String[] strArray = { "hello", "world", "java" };
        // List list = Arrays.asList(strArray);
 
        List 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);
        }
    }
注意事项:
       虽然可以把数组转成集合,但是 集合的长度不能改变
asList接收可变参数,Arrays.asList("hello", "world", "java");//可以
                               Arrays.asList("hello", "world");//也可以
 
13.一个案例:集合 嵌套存储和遍历元素的案例
集合的嵌套遍历
  需求:
          我们班有学生,每一个学生是不是一个对象。所以我们可以使用一个集合表示我们班级的学生。ArrayList
         但是呢,我们旁边是不是还有班级,每个班级是不是也是一个ArrayList
         而我现在有多个ArrayList。也要用集合存储,怎么办呢?
          就是这个样子的:ArrayList>
 
 
案例图解
 
public static void main(String[] args) {
        // 创建大集合
        ArrayList> bigArrayList = new ArrayList>();
 
        // 创建第一个班级的学生集合
         ArrayList firstArrayList = new ArrayList();
        // 创建学生
        Student s1 = new Student("唐僧", 30);
        Student s2 = new Student("孙悟空", 29);
        Student s3 = new Student("猪八戒", 28);
        Student s4 = new Student("沙僧", 27);
        Student s5 = new Student("白龙马", 26);
        // 学生进班
        firstArrayList.add(s1);
        firstArrayList.add(s2);
        firstArrayList.add(s3);
        firstArrayList.add(s4);
        firstArrayList.add(s5);
        // 把第一个班级存储到学生系统中
         bigArrayList.add(firstArrayList);
 
        // 创建第二个班级的学生集合
         ArrayList secondArrayList = new ArrayList();
        // 创建学生
        Student s11 = new Student("诸葛亮", 30);
        Student s22 = new Student("司马懿", 28);
        Student s33 = new Student("周瑜", 26);
        // 学生进班
        secondArrayList.add(s11);
        secondArrayList.add(s22);
        secondArrayList.add(s33);
        // 把第二个班级存储到学生系统中
         bigArrayList.add(secondArrayList);
 
        // 创建第三个班级的学生集合
         ArrayList thirdArrayList = new ArrayList();
        // 创建学生
        Student s111 = new Student("宋江", 40);
        Student s222 = new Student("吴用", 35);
        Student s333 = new Student("高俅", 30);
        Student s444 = new Student("李师师", 22);
        // 学生进班
        thirdArrayList.add(s111);
        thirdArrayList.add(s222);
        thirdArrayList.add(s333);
        thirdArrayList.add(s444);
        // 把第三个班级存储到学生系统中
         bigArrayList.add(thirdArrayList);
 
        // 遍历集合
         for (ArrayList array : bigArrayList) {
             for (Student s : array) {
                System.out.println(s.getName() + "---" + s.getAge());
            }
        }
    }
 
14.第二个案例
 
获取10个1-20之间的随机数,要求不能重复
 
用数组实现, 但是数组的长度是固定的,长度不好确定
  所以我们使用集合实现
  
  分析:
          A:创建产生随机数的对象
         B:创建一个存储随机数的集合。
          C:定义一个统计变量。从0开始。
          D:判断统计遍历是否小于10
              是:先产生一个随机数,判断该随机数在集合中是否存在。
                      如果不存在:就添加,统计变量++。
                      如果存在:就不搭理它。
              否:不搭理它
          E:遍历集合
 
 
实现代码参考
public static void main(String[] args) {
         // 创建产生随机数的对象
        Random r = new Random();
 
        // 创建一个存储随机数的集合。
        ArrayList array = new ArrayList();
 
        // 定义一个统计变量。从0开始。
        int count = 0;
 
        // 判断统计遍历是否小于10
        while (count < 10) {
            //先产生一个随机数
            int number =  r.nextInt(20) + 1;
 
            //判断该随机数在集合中是否存在。
            if(!array. contains(number)){
                //如果不存在:就添加,统计变量++。
                array.add(number);
                count++;
            }
        }
 
        //遍历集合
        for(Integer i : array){
            System.out.println(i);
        }
    }
 
15.案例3
 
  需求:键盘录入多个数据, 以0结束,要求在控制台输出这多个数据中的 最大值
  
 分析:
          A:创建键盘录入数据对象
          B:键盘录入多个数据,我们不知道多少个,所以用集合存储
          C:以0结束,这个简单,只要键盘录入的数据是0,我就不继续录入数据了
          D:把集合转成数组
          E:对数组排序
          F:获取该数组中的最大索引的值
 
示例代码
public static void main(String[] args) {
        // 创建键盘录入数据对象
        Scanner sc = new Scanner(System.in);
 
        // 键盘录入多个数据,我们不知道多少个,所以用集合存储
        ArrayList array = new ArrayList();
 
        // 以0结束,这个简单,只要键盘录入的数据是0,我就不继续录入数据了
        while (true) {
            System.out.println("请输入数据:");
            int number = sc.nextInt();
            if (number != 0) {
                array.add(number);
            } else {
                break;
            }
        }
 
        // 把集合转成数组
        // public  T[] toArray(T[] a)
        Integer[] i = new Integer[array.size()];
        // Integer[] ii = array.toArray(i);
        array.toArray(i);
        // System.out.println(i);
        // System.out.println(ii);
 
        // 对数组排序
        // public static void sort(Object[] a)
        Arrays.sort(i);
 
        // 获取该数组中的最大索引的值
        System.out.println("数组是:" + arrayToString(i) + "最大值是:"
                + i[i.length - 1]);
    }
 
    public static  String  arrayToString(Integer[] i) {
         StringBuilder sb = new StringBuilder();
 
        sb.append("[");
        for (int x = 0; x < i.length; x++) {
            if (x == i.length - 1) {
                sb.append(i[x]);
            } else {
                sb.append(i[x]).append(", ");
            }
        }
        sb.append("]");
 
        return  sb.toString();
    }
几个注意或者有疑问的地方
 
 

你可能感兴趣的:(J2SE)