0
点赞
收藏
分享

微信扫一扫

Java集合学习

kmoon_b426 2022-04-05 阅读 98

Collection

结构图

遍历

  1. 普通for循环
  2. 增强for循环
  3. iterator

泛型

ArrayList<E>使用时确定E的类型,确定集合中存放的datatype。编译时检查出来,存引用的datatype。
不使用泛型:什么引用类型都可以添加。

public class Test01 {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        //创建一个ArrayList集合,向这个集合中存入学生的成绩:
         ArrayList al = new ArrayList();
         al.add(98);
         al.add(18);
         al.add(39);
         al.add(60);
         al.add(83);
         al.add("丽丽");
         //对集合遍历查看:
         for(Object obj:al){
             System.out.println(obj);
         }
    }
}

输出结果
使用泛型,编译期进行检查

public static void main(String[] args) {
        //创建一个ArrayList集合,向这个集合中存入学生的成绩:
        // 加入泛型的优点:在编译时期就会对类型进行检查,不是泛型对应的类型就不可以添加入这个集合。
         ArrayList<Integer> al = new ArrayList<Integer>();
         al.add(98);
         al.add(18);
         al.add(39);
         al.add(60);
         al.add(83);
         /*al.add("丽丽");        al.add(9.8);*/
        //对集合遍历查看:
         /*for(Object obj:al){
               System.out.println(obj);
         }*/
        for(Integer i:al){
            System.out.println(i);
        }
    }
  1. 自定义泛型
    泛型类
    ClassName<A> 相当于占位。但是现在确定的是这个类型一定是一个引用数据类型,而不是基本数据类型
public class GenericTest<E> {
    int age;
    String name;
    E sex;
    public void a(E n){

    }
    public void b(E[] m){

    }
}

class Test{
    //这是main方法,程序的入口
     public static void main(String[] args) {
         //GenericTest进行实例化:
         // (1)实例化的时候不指定泛型:如果实例化的时候不明确的指定类的泛型,那么认为此泛型为Object类型
          GenericTest gt1 = new GenericTest();
          gt1.a("abc");
          gt1.a(17);
          gt1.a(9.8);
          gt1.b(new String[]{"a","b","c"});
          //(2)实例化的时候指定泛型:---》推荐方式
          GenericTest<String> gt2 = new GenericTest<>();
          gt2.sex = "男";
          gt2.a("abc");
          gt2.b(new String[]{"a","b","c"});
     }
}

继承
ClassName2 extends GenetricName1<Integer>

应用场合
泛型继承应用
细节:
泛型类可以定义多个参数类型:
定义多个参数类型
静态方法不能使用泛型。
不能用E[]创建。
泛型方法
要求:
(1)这个方法的泛型的参数类型要和当前的类的泛型无关
(2)前面加上<T>,否则会把T当成一种数据类型
(3)T类型在调用方法时确定。
(4)可以是静态方法。

// 不是
public static void a(E e){}
// 是
public static <T> void a(T e){}
// E和类的泛型一样,不是
public <E> void a(E e){}

泛参继承
子类A,父类B。G<A>G<B>无继承关系。仅编译器写代码时限制。
泛参继承

  1. 通配符
    因为泛型参数无法重载,因此需要使用通配符。
// 报错
public void a(List<String> list){}
public void a(List<Integer> list){}

使用G<?>即可,其是G<A>,G<B>的父类。

public void a(List<?> list){
   //内部遍历的时候用Object即可,不用? 
   for(Object a:list){
       System.out.println(a); 
   } 
}

细节
不可随意写入数据,只能写入null。

list.add("abc"); // 报错
list.add(null);
Object s = list.get(0); // 读取
  1. 泛型受限
// 开始使用泛型受限:泛型的上限
List<? extends Person>:
// 就相当于:   
List<? extends Person>List<Person>的父类,是List<Person的子类>的父类

// 开始使用泛型受限:泛型的下限
List<? super Person>:
// 就相当于:   
List<? super Person>List<Person>的父类,是List<Person的父类>的父类

List接口

  1. ArrayList1.7
    (1)1.5倍扩容,初始为10
    (2)底层使用elementData
    ArrayList1.7
  2. ArrayList1.8
    (1)1.5倍扩容,初始为0。首次add时,扩容为10,节省内存。
    (2)依旧使用Object类型数组。
  3. Vector
    (1)2倍扩容。
    (2)线程安全。synchronize add
  4. LinkedList
    (1)添加元素:add有异常;offer无异常。
    (2)弹出元素:remove有异常,poll无异常

迭代器

迭代器
hasNext(), next()
hasNext(),next()
增强for循环底层是通过迭代器实现。
ListIterator迭代器
原iter和集合操作不可同时进行。通过ListIterator,迭代和添加都是靠一个ListIterator来完成。

// 报错
Iterator<String> it = list.iterator();
while(it.hastNext()){
	if ("cc".equals(it.next()){
		list.add("kk");
	}
}

补充:比较器使用

  1. 比较String
    a.compareTo(b);
  2. 比较double
    ((Double) a).compareTo((Double) b);
  3. 自定义数据类型
    (1)内部比较器:实现compareTo方法。
    (2)外部比较器:实现Comparator<XX>类。多态,扩展性好。

Set

唯一,无序。
遍历:增强for,iterator。

  1. HashSet
    HashSet
    底层是HashMap
  2. LinkedHashSet
    在HashSet基础上多了一个总的链表,将放入的元素串在一起,方便有序遍历。
  3. TreeSet
    唯一,输入顺序不保留,数值上升序。底层二叉树。
    树中存放自定义类型需要实现比较器,一般用外部比较器。

Map

Map结构图

  1. Hashtable
    低效,线程安全,不可存null
  2. TreeMap
    唯一,数值有序,需要实现比较器(外部)。
  3. LinkedHashMap
    hash+list,按输入顺序输出。
  4. HashMap
    无序,唯一。可存null(也唯一),线程不安全。
    2倍扩容,初始16,装填因子0.75.
    设置2倍扩容的好处
    (1)h&(len-1)<=>h%len,计算位置快捷,取模效率低。等效的前提是2倍扩容。
    (2)防止hash位置冲突。不是2的整数倍,哈希冲突概率高。
    2倍扩容计算哈希值
    扩容后

不是2倍扩容

Collections工具类

(1)不支持创建对象。因为构造器私有化了。
(2)里面的属性和方法都被static修饰,可以直接用Collections.method()调用。

常用方法
(1)addAll
(2)binarySearch&sort
(3)copy
(4)fill填充

Stack

是Vector的子类,add返回True,push返回插入的值。

同步类容器

把ArrayList, HashMap等变成线程安全的:
List list = Collections.synchronizedList(new ArrayList());
原理:mutex+synchronized
原理

ConcurrentMap并发容器

(1)ConcurrentHashMap代替HashMap, HashTable。
分出16个片区,单独加锁,性能高。
(2)ConcurrentSkipListMap代替TreeMap。

COW并发容器

写时复制,读写分离。
复制旧容器到新容器,再添加元素,换指针。
(1)CopyOnWriteArrayList
(2)CopyOnWriteArraySet
调用add,每次调用addIfAbsent遍历数组,性能低于CopyOnWriteArrayList。

队列

阻塞队列
BlockingQueue继承Queue,Queue继承自Collection
添加:

  1. add(E e) 无空间抛异常IllegalStateException。
  2. offer(E e) 无空间返回false。
  3. put(E e) 无空间则阻塞

查询:

  1. take() 获取并移除头部,可用前阻塞。
  2. poll(long timeout, TimeUnit unit) 获取并移除头部,可用前指定时间前阻塞。
    删除:
    remove(Object o) 移除指定

阻塞队列常见子类

  1. ArryaBlockingQueue
    put&take阻塞

(1)不可同时读写,同一把锁。
(2)不可添加null。
(3)得到头元素不删除:peek
(4)notFull&notEmpty是两个队列。

  1. LinkedBlockingQueue
    (1)可同时读写,两把锁。
    (2)可选择有边界(指定长度的话)。此时put&take可阻塞。
    (3)count&getAndIncrement()

  2. SynchronousQueue
    先取才能加元素,队列没有容量。
    意义:提高方便高效的进行线程间数据的传送。效率极高,不会产生队列数据争抢问题。
    意义
    取出元素 不能用peek,因为peek不会将元素从队列中拿走,只是查看的效果;

  3. PriorityBlockingQueue
    (1)无界,默认初始11.
    (2)不可放null。
    (3)不可放入不可比较的对象。会抛ClassCastException。
    (4)取元素时,以CompareTo优先级传出。

  4. DelayQueue
    无界,用于放置实现了Delayed接口的对象,其中的对象只能在到期时才被拿走。
    元素必须实现了Comparable。重写getDelay和compareTo。
    用处:
    (1)淘宝订单业务:下单之后如果三十分钟之内没有付款就自动取消订单。
    (2)饿了吗订餐通知:下单成功后60s之后给用户发送短信通知。
    (3)关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
    (4)缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
    (5)任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等。

双端队列Deque

两头都可存取。
实现类:LinkedList

举报

相关推荐

0 条评论