Java集合框架及基本接口

Collection接口及迭代器

Collection接口继承Iterable接口。

Collection接口有两个方法,add()和iterator();

add():向实现接口的集合中添加元素;

iterator():所有实现Iterable接口的集合都可以通过该方法来遍历集合中的元素;

/***
 * ArrayList是Collection接口的一个实现
 * **/
List<String> list = new ArrayList<>();
list.add("123");
list.add("ABC");
/***
 * 方式一:iterator()获得迭代器遍历
 * **/
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

/***
 *方式二:for遍历方式
 * **/
for (String str : list
) {
    System.out.println(str);
}

泛型方法的使用

从Collection接口和Iterable接口可以看出,这两个都是泛型接口,这两个接口实现的集合可以存放任意数据类型的元素,极大提高了代码的复用性。下面例子简单介绍了这种思想,判断任何类型集合中是否有某个元素。

  /**
     * ArrayList
     * **/
    List<String> list = new ArrayList<>();
    list.add("123");
    list.add("ABC");
    /**
     * ArrayDeque
     * **/
    Queue<String> deque = new ArrayDeque<>();
    deque.add("123");
    deque.add("ABC");
    boolean flag = GenericParadigmTest.isEqual(list, "123");
    System.out.println(flag);
    boolean flag2 = GenericParadigmTest.isEqual(deque, 1234);
    System.out.println(flag2);

}

/**
 * 泛型方法的使用:判断某个元素在集合中是否存在
 ***/
public static <E> boolean isEqual(Collection<E> es, Object o) {
    for (E e : es) {
        if (e.equals(o)) {
            return true;
        } else {
            return false;
        }
    }
    return false;
}

集合基本接口和实现

Java中集合的基本接口有Collection和Map。一个是单元素(Value)集合,另一个是键值对(Key-Value)集合。

继承Collection的接口有List、Set、Queue。

List

List实现的集合是有序可重复元素集合。List的常见实现:ArrayList、LinkedList。

ArrayList

ArrayList封装了一个动态数组,在连续的地址中存放者对象的引用,可自动扩容。查找元素速度块,但插入和删除元素的速度慢,因为每次插入和删除元素需要将后面的所有元素移动来保持有序性。

LinkedList

LinkedList是一个链表结构,每一个节点存放着下一个节点的引用,节点间存放的内存空间不是连续的。查询元素的时候慢,需要从头节点开始遍历,但查询和删除元素快,只需要更改目标节点前后的引用即可。

LinkedList.add()方法只能往链表尾部添加元素。

要想往链表任何位置添加元素或者修改元素,可以使用ListIterator.listIterator()方法。这个方法可以通过迭代器往链表任何位置添加元素。

/**
  * LinkedList.add()方法只能往链表尾部添加元素
  * ***/
 List<Integer> staff = new LinkedList<>();
 staff.add(1);
 staff.add(2);
 staff.add(3);
 Iterator<Integer> iterator = staff.iterator();
 System.out.println("LinkedList.add()方法往链表尾部添加元素:" + staff);
 /**
  *ListIterator.listIterator()方法可以通过迭代器往链表任何位置添加元素
  * **/
 List<Integer> staff2 = new LinkedList<>();
 staff2.add(12);
 staff2.add(23);
 ListIterator<Integer> listIterator = staff2.listIterator();
 listIterator.next();
 listIterator.add(34);
 System.out.println("ListIterator.add()方法可以通过迭代器往链表任何位置添加元素:" + staff2);
 listIterator.next();
 listIterator.add(11111);
 System.out.println("ListIterator.set()方法可以通过迭代器修改链表任何位置元素:" + staff2);

 /**
  * 后序遍历
  * **/
 while (listIterator.hasPrevious()) {
     System.out.println(listIterator.previous());
 }
LinkedList.add()方法往链表尾部添加元素:[1, 2, 3]
ListIterator.add()方法可以通过迭代器往链表任何位置添加元素:[12, 34, 23]
ListIterator.set()方法可以通过迭代器修改链表任何位置元素:[12, 34, 23, 11111]
11111 23 34 12

ListIterator接口和Iterable接口的区别

在上面我们使用到了ListIterator,而ListIterator接口继承Iterable接口。

他们之间的区别如下:

ListIterator可以往List中添加元素和修改元素,而Iterable不能;

ListIterator和Iterable都可以顺序遍历集合,但ListIterator还可以倒叙遍历集合;

ListIterator和Iterable都可以删除元素。

如果需要频繁进行插入和删除操作的情况可以使用链表结构存储数据,如下:

public static void main(String[] args) {
    List<String> a = new LinkedList<>();
    a.add("amy");
    a.add("carl");
    a.add("erica");
    System.out.println(a);

    List<String> b = new LinkedList<>();
    b.add("bob");
    b.add("doug");
    b.add("frances");
    b.add("gloria");
    System.out.println(b);

    /***
     * 将链表b的元素合并到链表a
     * **/
    ListIterator<String> aIter = a.listIterator();
    Iterator<String> bIter = b.iterator();
    while (bIter.hasNext()) {
        if (aIter.hasNext())
            aIter.next();
        aIter.add(bIter.next());
    }
    System.out.println(a);

    /***
     * 将链表b的元素删除
     * **/
    while (bIter.hasNext()) {
        bIter.next();
        while (bIter.hasNext()){
            bIter.next();
            bIter.remove();
        }
    }
    System.out.println(b);
    /**
     * 从a中移除所有b的元素
     * ***/
    a.removeAll(b);
    System.out.println(a);

}
[amy, carl, erica]
[bob, doug, frances, gloria]
[amy, bob, carl, doug, erica, frances, gloria]
[bob, doug, frances, gloria]
[amy, carl, erica]

Set

Set实现的集合是不可重复集合.

Set接口常见的实现有:HashSet、TreeSet。

HashSet

HashSet是一个散列集,插入元素时随机分布在散列表中,使用迭代器遍历散列表时元素的顺序也是随机的,但不允许重复元素插入。

TreeSet

TreeSet是一个树集,按任意顺序插入元素,在树上会自动进行排序,遍历时会按照排序好的顺序进行输出。

例如,从TreeSet输入三个元素,再遍历输出。

public static void main(String[] args) {
    Set<String> sorts = new TreeSet<>();
    sorts.add("huan");
    sorts.add("bao");
    sorts.add("long");
    for (String s : sorts) {
        System.out.println(s);
    }
}
bao
huan
long

使用树集需要元素对象实现Comparable接口并实现其中的compareTo()方法或者自己实现一个Comparator比较器。

例如,定义一个Item类来实现Comparable接口时遍历集合元素按compareTo()方法的逻辑来进行元素排序;

定义Comparator比较器时遍历集合元素按比较器的逻辑来进行元素排序。

package com.teasir.collection.set;

import java.util.Objects;

public class Item implements Comparable<Item> {

    private String descripton;
    private int number;

    public Item(String descripton, int number) {
        this.descripton = descripton;
        this.number = number;
    }

    public String getDescripton() {
        return descripton;
    }

    public void setDescripton(String descripton) {
        this.descripton = descripton;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Item item = (Item) o;
        return number == item.number &&
                descripton.equals(item.descripton);
    }

    @Override
    public int hashCode() {
        return Objects.hash(descripton, number);
    }

    @Override
    public String toString() {
        return "Item{" +
                "descripton='" + descripton + '\'' +
                ", number=" + number +
                '}';
    }

    @Override
    public int compareTo(Item o) {
        int diff = Integer.compare(number, o.getNumber());
        return diff != 0 ? diff : descripton.compareTo(o.getDescripton());
    }
}
  package com.teasir.collection.set;
    
    import java.util.Comparator;
    import java.util.Set;
    import java.util.TreeSet;
    
    public class TreeSetTest {
        public static void main(String[] args) {
            /**
             * 按照Item默认的排序方式排序
             * **/
            Set<Item> items = new TreeSet<>();
            items.add(new Item("huan", 1224));
            items.add(new Item("bao", 4544));
            items.add(new Item("long", 345));
            System.out.println(items);
            /**
             * 定义一个Comparator对元素进行排序
             * **/
            Set<Item> itemSelf=new TreeSet<>(Comparator.comparing(Item::getDescripton));
            itemSelf.addAll(items);
            System.out.println(itemSelf);
        }
    }
[Item{descripton='long', number=345}, Item{descripton='huan', number=1224}, Item{descripton='bao', number=4544}]
[Item{descripton='bao', number=4544}, Item{descripton='huan', number=1224}, Item{descripton='long', number=345}]

Queue

Queue接口实现的是一个队列结构,存储元素的特点是先进先出。队列的常见两种实现:ArrayDeque、LinkedList、PriorityQueue。

ArrayDeque和LinkedList

循环数组ArrayDeque效率比链表LinkedList高;

循环数组ArrayDeque是一个有界集合,如果存放的元素无限,则使用链表实现队列更合适

ArrayDeque和LinkedList都可以实现双端队列,都可以从队列头和尾插入和删除元素。

PriorityQueue

PriorityQueue为优先队列,跟之前提到的TreeSet概念大同小异,会对插入队列的元素按一定的规则进行排序,遍历和删除的时候都会按照排序好的顺序进行相应操作。

例如,使用优先队列实现按时间顺序将最久远的数据删除功能,但这些数据插入队列时的顺序并不是按照时间来插入的。

  package com.teasir.collection.Queue;
    
    import java.time.LocalDate;
    import java.util.PriorityQueue;
    import java.util.Queue;
    
    public class PriorityQueueTest {
        public static void main(String[] args) {
            Queue<LocalDate> prtQueue=new PriorityQueue<>();
            prtQueue.add(LocalDate.of(2022,1,12));
            prtQueue.add(LocalDate.of(2022,2,23));
            prtQueue.add(LocalDate.of(2022,1,06));
            System.out.println(prtQueue);
            while (!prtQueue.isEmpty()){
                System.out.println(prtQueue.remove());
            }
        }
    }


[2022-01-06, 2022-02-23, 2022-01-12]
2022-01-06
2022-01-12
2022-02-23

Map

Map接口常见的实现有HashMap、TreeMap、LinkedHashMap、HashTable、ConcurrentHashMap。

TreeMap

TreeMap跟之前的TreeSet、PriorityQueue会将插入元素按一定的逻辑进行排序。

HashTable和ConcurrentHashMap

HashTable跟HashMap差不多,但他是线程安全的,现在基本不会使用HashTable,如果需要考虑线程安全需要使用ConcurrentHashMap,而不是HashTable。

LinkedHashMap

LinkedHashMap会记住插入元素的顺序,按照插入元素的顺序进行排序。

例如,往LinkedHashMap按一定顺序插入元素,遍历时发现顺序与插入顺序相同。

package com.teasir.collection.map;

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapTest {
    public static void main(String[] args) {
        Map<String,String> staff=new LinkedHashMap();
        staff.put("long","243");
        staff.put("huan","22343");
        staff.put("bao","2443");

        /**
         *key的遍历
         * */
        for(String key:staff.keySet()){
            System.out.println(key);
        }
        /**
         * key和value的遍历
         * **/
        for(Map.Entry entry:staff.entrySet()){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }

    }
}
long
huan
bao
long:243
huan:22343
bao:2443

LinkedHashMap可以按照"最少使用原则"来设计一个缓存器,缓存里面只存储最近有使用过的元素,如果超过了规定的元素,缓存会自动删除,只保留符合条件的元素。

例如,设计一个只缓存10条数据的缓存器,多余元素从缓存中清除。

 package com.teasir.collection.map;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class LinkedHashMapTest {
        public static void main(String[] args) {
            Map<String, String> staff = new LinkedHashMap<String, String>(16, 0.75F, true) {
                protected boolean removeEldestEntry(Map.Entry<String, String> entry) {
                    return size() > 10;
                }
            };
            staff.put("long", "243");
            staff.put("huan", "22343");
            staff.put("bao", "2443");
            staff.put("longg", "243");
            staff.put("huann", "22343");
            staff.put("baoo", "2443");
            staff.put("long2", "243");
            staff.put("huan2", "22343");
            staff.put("bao2", "2443");
            staff.put("longg2", "243");
            staff.put("huann2", "22343");
            staff.put("baoo2", "2443");
            staff.put("long3", "243");
            staff.put("huan4", "22343");
            staff.put("bao5", "2443");
            staff.put("longg6", "243");
            staff.put("bo", "超出元素");
            /**
             * key和value的遍历
             * **/
            for (Map.Entry entry : staff.entrySet()) {
                System.out.println(entry.getKey() + ":" + entry.getValue());
            }
    
        }
    }
   huan2:22343
    bao2:2443
    longg2:243
    huann2:22343
    baoo2:2443
    long3:243
    huan4:22343
    bao5:2443
    longg6:243
    bo:超出元素

总结

1、Collection接口继承Iterable接口,每一个实现Collection接口的集合都可以通过迭代器遍历元素。
2、Java中集合的基本接口有Collection和Map。
3、继承Collection的接口有List、Set、Queue。
4、List的常见实现:ArrayList、LinkedList。
ArrayList底层实现是数组,元素在内存中的位置是连续的,可以通过索引快速查询指定位置的元素,但修改和删除元素时,需要移动该操作元素后续的所有元素;
LinkedList的底层实现是链表,元素在内存中的位置是不连续的,元素之间通过指针间的引用连接,查询时需要从头节后开始遍历,修改和删除元素时修改节点的引用即可。
5、Set接口常见的实现有:HashSet、TreeSet。
6、队列的常见两种实现:ArrayDeque、LinkedList、PriorityQueue。
ArrayDeque和LinkedList都可以实现双端队列。
7、Map接口常见的实现有HashMap、TreeMap、LinkedHashMap、HashTable、ConcurrentHashMap。
HashTable跟HashMap差不多,但他是线程安全的,现在基本不会使用HashTable,如果需要考虑线程安全需要使用ConcurrentHashMap,而不是HashTable。
LinkedHashMap会记住插入元素的顺序,按照插入元素的顺序进行排序。
8、TreeMap、TreeSet、PriorityQueue会将插入元素按一定的逻辑进行排序。这三个集合存储的元素必须实现Comparable接口或者实现一个Comparator比较器。

参考文章

https://blog.csdn.net/qq_18433441/article/details/78221810

https://www.cnblogs.com/wxd0108/p/5906618.htmlb

https://blog.csdn.net/weixin_39241397/article/details/79687789

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值