JavaSE进阶知识(二)集合和IO流

集合

集合不能直接存储基本数据类型,也不能直接储存java对象,集合存储的是对象的内存地址

所有的集合类和接口都在java.util包下

集合的继承结构图

java.lang.Collection接口常用方法

没有使用泛型之前,Collection中可以存储Object的所有子对象

使用泛型后,Collection中只能存储某个具体的类型

public static void main(String[] args) {
    Collection c = new ArrayList();
    c.add(100);  // 自动装箱,实际上放进去了一个对象的内存地址  Integer x = new Integer(100) ,x指向的内存地址放进去了
    c.add(3.14);
    c.add(new Object());
    System.out.println(c.size());  // 3

    Object[] a = c.toArray();
    for (int i = 0; i < a.length; i++) {
        System.out.println(a[i]); // 输出的都是java对象toString后的内容  100 3.14 java.lang.Object@483bf400
    }

    c.clear();
    System.out.println(c.size());  // 0

    c.add("hello");
    c.add("world");
    System.out.println(c.contains("hello"));  // true
    c.remove("world");
    System.out.println(c);
    System.out.println(c.isEmpty());  // false
}

Collection接口的contains和remove方法深入理解

public static void main(String[] args) {
    Collection c = new ArrayList();
    String s1 = new String("abc");
    String s2 = new String("def");

    c.add(s1);
    c.add(s2);
    String x = new String("abc");
    System.out.println(c.contains(x));  // true 因为 contains方法底层调用了equals方法,equals比较的是内容不是内存地址
}
public class Test04 {
    public static void main(String[] args) {
        User u1 = new User("Vansal");
        User u2 = new User("Vansal");
        Collection c = new ArrayList();
        c.add(u1);
        // User类没重写equals方法前
        boolean b1 = c.contains(u2);  // false 因为User类没有重写equals方法,会调用父类Object的equals方法比较内存地址,所以false,重写后为true

        // 重写后
        User u3 = new User("Vansal");
        c.remove(u3);  // remove方法同理,底层也是用equals判断的
        System.out.println(c.size());  // 0
    }
}

class User {
    String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(name, user.name);
    }
}

 

集合迭代/遍历

public static void main(String[] args) {
    Collection c = new ArrayList();
    c.add(100);
    c.add("a");
    c.add("b");
    // 要对c进行遍历,先获取该对象的迭代器
    Iterator it = c.iterator();
    // 通过迭代器对象对集合进行遍历
    System.out.println(it.next());
    while (it.hasNext()) {
        System.out.println(it.next());  // 取出来的都是对象 100 a b
    }

}

集合元素的删除

集合的结构发生改变后,一定要重新获取迭代器,不然会报ConcurrentModificationException错误

下面代码c.remove(o)虽然集合c删除了这个对象,但是迭代器中还存在这个对象的快照,两者不符就会报错

用迭代器去删除时会自动更新迭代器和集合

public class Test05 {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add(1);
        c.add(2);
        c.add(3);

        Iterator it = c.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            // c.remove(o);  会报ConcurrentModificationException错误 要使用迭代器的remove方法删除
            it.remove(); // 删除迭代器指向的当前元素
            System.out.println(o);
        }
        System.out.println(c.size()); // 0
    }
}

List接口特有的方法

public class Test06 {
    public static void main(String[] args) {
        List myList = new ArrayList();
        myList.add(1);
        myList.add(2);
        myList.add(3);
        // 在列表的指定位置插入元素,这个方法使用不多,因为对ArrayList集合涞水效率较低
        myList.add(1, "aaa");

        Iterator it = myList.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            System.out.println(o);  // 1 aaa 2 3
        }
        // 根据下标获取元素
        Object a = myList.get(1);
        System.out.println(a);
        // 因为有下标,List集合就有自己特殊的遍历方式
        for (int i = 0; i < myList.size(); i++) {
            System.out.println(myList.get(i));
        }
        // 获取指定对象在集合中第一次出现的索引
        System.out.println(myList.indexOf("aaa"));  // 1
        // 获取指定对象在集合中最后一次出现的索引
        System.out.println(myList.lastIndexOf("aaa"));  // 1
        // 删除指定下标的元素
        myList.remove(1);
        System.out.println(myList);  // [1, 2, 3]
        // 修改指定下标的元素
        myList.set(1,100);
        System.out.println(myList); // [1, 100, 3]
    }
}

ArrayList类详解

public static void main(String[] args) {
    // 默认初始化容量是10
    ArrayList arr1 = new ArrayList();
    // 指定初始化容量
    ArrayList arr2 = new ArrayList(20);

    Collection c = new HashSet();
    c.add(1);
    c.add(2);
    c.add(3);
    // 可以传入一个集合,将HashSet转换为ArrayList
    ArrayList arr3 = new ArrayList(c);
    System.out.println(arr3);  // [1, 2, 3]

}

LinkedList类详解

单向链表数据结构

链表优点:随机增删元素效率较高,因为增删元素不涉及到大量元素位移的问题

链表缺点:查询效率比较低,因为链表的内存地址不连续,每一次查找元素都需要从头节点开始往下遍历

删除元素时

 双向链表数据结构

 

Vector类详解

Vector中所有的方法都是同步的,是线程安全的,所以效率比较低,使用较少

非线程安全转换为线程安全

public static void main(String[] args) {
    List myList = new ArrayList();
    Collections.synchronizedList(myList);
    myList.add(1);
    myList.add(2);
    myList.add(3);
}

集合总结

需要检索查找的选择ArrayList,需要增删的选择LinkedList,一般我们加元素都是在末尾添加,所以ArrayList用的更多

泛型

public class Test09 {
    public static void main(String[] args) {
        List<Animal> myList = new ArrayList<>();
        Animal c = new Cat();
        Animal b = new Bird();
        myList.add(c);
        myList.add(b);
        // 使用泛型后,除了Animal和Animal的子类外,其他都不行
        //  myList.add(new Object()); 编译不通过,报错

        Iterator<Animal> it = myList.iterator();
        while (it.hasNext()) {
            // 使用泛型之后,每一次返回的数据都是Animal类型,就不需要进行强制类型转换
            Animal a = it.next();
            a.move();
        }
    }
}

class Animal {
    public void move() {
        System.out.println("动物在移动");
    }
}

class Cat extends Animal {
    public void move() {
        System.out.println("猫在抓老鼠");
    }
}

class Bird extends Animal {
    public void move() {
        System.out.println("鸟在飞翔");
    }
}

泛型的优缺点

优点:集合中存储的元素类型统一了,从集合中取出元素类型是泛型指定的类型,不需要进行大量的向下转型了

缺点:导致集合中的元素缺乏多样性

自定义泛型

自定义泛型时,<>内是一个标识符,可以随便写

一般用<E>或<T>,E代表Element元素,T代表Type类型

public class Customize<T> {
    public static void main(String[] args) {
        // new对象时指定了泛型的类型为String
        Customize<String> c1 = new Customize<>();
        // doSome方法只能传String类型的参数
        c1.doSome("Vansal");

        Customize<Integer> c2 = new Customize<>();
        c2.doSome(100);
        Integer a = c2.getBack(100);
        System.out.println(a);

        Customize<A> c3 = new Customize<>();
        A a1 = c3.getBack(new A());
        System.out.println(a1); // A
    }

    public void doSome(T o) {
        System.out.println(o);
    }

    public T getBack(T t) {
        return t;
    }
}

class A {
    public String toString() {
        return "A";
    }
}

增强for循环(foreach)

缺点:没有下标


                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风里有诗句哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值