【Java】类集

核心接口

Collection、List、Set、Map、Iterator、Enumeration、Queue、ListIterator

Collection接口

java.util.Collection是单值集合操作的最大的父接口,在该接口之中定义有所有的单值数据的处理操作。

核心操作方法:

No 方法名称 描述
1 public boolean add(E e) 向集合中添加数据
2 public boolean addAll(Collection<?extends E> c) 向集合中添加一组数据
3 public void clear() 清空集合
4 public boolean contains(Object o); 查找数据是否存在,需要使用equals()方法
5 public-boolean remove(Object o); 删除数据,需要equals()方法
6 publicint size0(); 取得集合长度
7 public Obiect[] toArray(); 将集合变为对象数组返回
8 public lterator iterator(); 将集合变成Iterator接口

最常用的两个方法:add()数据添加,iterator()输出。

在实际的开发中往往考虑使用Collection的子接口:List和Set。


List接口

允许保存有重复元素。List拥有的方法比Collection中的要多。

No 方法名称 描述
1 public E get(int index); 获取指定索引上的数据
2 public E set(int index,E element); 修改指定索引数据
3 public ListIterator listIterator(); 返回ListIterator接口对象

由于List本身还是接口,要想取得接口的实例化对象,就必须有子类,在List接口下有三个常用子类:ArrayList(实际开发占90%)、Vector、LinkedList。

ArrayList子类

ArrayList的继承结构:

常用方法代码:

List<String> list = new ArrayList<String>();//无参构造
List<String> list2 = new ArrayList<String>(10);//有参构造,参数为容量
list.add("Hello");//添加数据
list.size();//返回list长度
list.isEmpty();//判断list是否为空
list.remove("Hello");//移除第一个“Hello”
list.contains("ABC");//判断是否存在“ABC”
list.get(2);//返回下标为2的元素

ArrayList封装了数组。如果进行数据追加的时候,如果ArrayList长度不够,就会进行新的数组开辟(以2倍扩容),并进行拷贝。

在JDK1.9之后,无参是默认的空数组,使用的时候才会开辟空间。
在JDK1.9之前,无参是开辟为10的数组。

List存储特征:

  • 保存的顺序就是其存储顺序。
  • List集合里面允许存在有重复数据。

在使用List操作自定义类对象的时候,如果需要使用到contains(),remove()方法进行查询与删除处理的时候一定要保证已经成功覆写equals()方法。

class Person{
    private String name;
    private int age;
    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(obj == null){
            return false;
        }
        if(!(obj instanceof Person)){
            return false;
        }
        Person per = (Person)obj;
        return this.name.equals(per.name) && this.age == per.age;
    }
}

LinkedList子类

该子类的使用方法与ArrayList一致。

ArrayList与LinkedList区别:

  • ArrayList封装的是数组;LinkedList封装的是链表。
  • ArrayList时间复杂度为O(1),而LinkedList的复杂度为O(n)。

Vector子类(一般不会用)


Set接口

Set接口中不允许重复内容。Set接口并没有对Collection接口进行扩充,而List对Collection进行了扩充。因此,在Set接囗中没有get()方法。

HashSet(无序存储)

保存的数据是无序的。

HashSet的继承结构:

HashSet判重的方法是依靠Object类中的两个方法:

  1. hash码:public native int hashCode();
  2. 对象比较:public boolean equals(Object obj);

在Java中进行对象比较的操作有两步:

  1. 先利用hashCode()进行编码的匹配。
  2. 再调用equals()方法进行内容的比较。
    必须两个方法equals()、hashCode()返回值都相同才判断为相同。
class Person implements Comparable<Person>{
    private String name;
    private int age;

    @Override
    public int hashCode() {
        return Objects.hash(name,age);
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(obj == null || getClass() != obj.getClass()){
            return false;
        }
        Person person = (Person)obj;
        return Objects.equals(name,person.name) && Objects.equals(age,person.age);
    }
}

方法与上述类似。

TreeSet(有序存储)

TreeSet使用升序排列。

如果想要利用TreeSet对自定义类进行排序就需要在对象所在的类里是实现Comparable接口,并覆盖compareTo()方法。(原因:TreeSet本质是利用TreeMap子类实现存储,而TreeMap就需要Comparable来确定大小关系)

class Person implements Comparable<Person>{
    private String name;
    private int age;

    @Override
    public int compareTo(Person o) {
        if(this.age > o.age){
            return 1;
        }else if(this.age < o.age){
            return -1;
        }else {
            return this.name.compareTo(o.name);
        }
    }
}

由于如果类的属性太多,那么compareTo的比较就太多了,所以一般使用HashSet。


集合的输出

Iterator迭代输出(95%)

在Iterator接口里有如下方法:

No 方法名称 描述
1 public boolean hasNext() 判断是否有下一个数据
2 public E next() 取出当前数据
3 public default void remove() 删除(除非必要不要用)
public class JavaList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("Hello");
        list.add("world");
        list.add("Hello");
        list.add("Java");
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
    }
}

对如remove()方法,如果在迭代里使用Collection集合的remove方法会导致迭代失败。只有使用Iterator里的remove才不会产生异常。

Listiterator双向迭代输出

public class JavaList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("Hello");
        list.add("world");
        list.add("Hello");
        list.add("Java");
        System.out.println("从前向后输出");
        ListIterator<String> listIterator = list.listIterator();
        while(listIterator.hasNext()){
            System.out.println(listIterator.next());
        }
        System.out.println("从后向前输出");
        while(listIterator.hasPrevious()){
            System.out.println(listIterator.previous());
        }
    }
}

并且如果要想实现由后向前的输出,那么必须先进行从前向后的输出,否则就会失败。

Enumeration枚举输出

该方式只能够依靠Vector子类。

public class JavaList {
    public static void main(String[] args) {
        Vector<String> vector = new Vector<>();
        vector.add("Hello");
        vector.add("World");
        vector.add("Test");
        Enumeration<String> enumeration = vector.elements();
        while(enumeration.hasMoreElements()){
            System.out.println(enumeration.nextElement());
        }
    }
}

foreach输出

public class JavaList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("Hello");
        list.add("world");
        list.add("Hello");
        list.add("Java");
        for (String str: list) {
            System.out.println(str);
        }
    }
}

Map集合

Map会以K-V键值对的形式来保存数据。

用户可采用自定义类作为key。但一定要记得覆写Object类的hashCode()与equals()方法。

public interface Map<K,V>;

常用方法:

No 方法名称 描述
1 public V put(K key,V value); 向Map中追加数据。
2 public V get(object key); 根据key取得对应的value,如果没有返回null
3 public Set keySet(); 取得所有key信息、key不能重复
4 public Collection values(); 取得所有value信息,可以重复
5 public Set<Map.Entry<K,V>> entrySet(); 将Map集合变为Set集合

HashMap子类

public class JavaMap {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"Hello");
        map.put(2,"World");
        map.put(2,"Java");//由于K值相同,所以会进行覆盖保留最后一个
        map.put(3,"Map");
        System.out.println(map);
        System.out.println(map.get(2));
        System.out.println(map.get(10));//查不到返回null
        
        Set<Integer> set = map.keySet();
        Iterator<Integer> iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        Collection<String> collection = map.values();
        Iterator<String> iterator1 = collection.iterator();
        while(iterator1.hasNext()){
            System.out.println(iterator1.next());
        }

        Set<Map.Entry<Integer,String>> set1 = map.entrySet();
        Iterator<Map.Entry<Integer,String>> iterator2 = set1.iterator();
        while(iterator2.hasNext()){
            Map.Entry<Integer,String> entry = iterator2.next();//取出每一个Map.Entry对象
            System.out.println(entry.getKey()+" = "+entry.getValue());
        }
    }
}

HashMap内部实现点分析:

HashMap内部结构可以看作是数组和链表的解和。数组被分为一个个桶(bucket),通过哈希值决定了键值对在这个数组的寻址;哈希值相同的键值对,则以链表形式存储。如果链表大小超过属值(TREEIFY_THRESHOLD,8),图中的链表就会被改造为树形结构。

Hashtable子类

使用方法与HashMap类似。

区别:

No 区别 HashMap Hashtable
1 推出版本 JDK1.2 JDK1.0
2 性能 异步处理,性能高 同步处理,性能低
3 安全性 非线程安全 线程安全
4 null操作 允许存放null K-V都不允许出现null

TreeMap子类

TreeMap是一个可排序的Map子类,它是按照Key的内容排序的。


栈与队列

Stack栈

先进后出

public class JavaStack {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("A");//入栈
        stack.push("B");
        System.out.println(stack.push("C"));//虽然也可以打印,但是没意义
        System.out.println(stack.peek());//栈顶元素
        System.out.println(stack.pop());//出栈元素
    }
}

Queue队列

先进先出

Queue是一个接口,所以其实现需要依靠LinkedList。

public class JavaQueue {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        queue.add("A");
        queue.add("B");
        System.out.println(queue.peek());
        System.out.println(queue.poll());
    }
}

Collections工具类

public class JavaList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        Collections.addAll(list,"L","O","V","E");//添加元素
        Collections.reverse(list);//反转
        Collections.sort(list);//排序
        Collections.shuffle(list);//打乱顺序
        Collections.binarySearch(list,"L");//二分查找
        Collections.max(list);
        Collections.min(list);
        Collections.fill(list,"a");//用a替换list中所有元素
        List<String> list1 = new ArrayList<String>();
        Collections.addAll(list,"A","B","C","D");
        Collections.copy(list,list1);//将集合list1中的元素全部复制到list中,并且覆盖相应索引的元素
    }
}

总结:

//排序操作(主要针对List接口相关)
reverse(List list):反转指定List集合中元素的顺序
shuffle(List list):对List中的元素进行随机排序(洗牌)
sort(List list):对List里的元素根据自然升序排序
sort(List list, Comparator c):自定义比较器进行排序
swap(List list, int i, int j):将指定List集合中i处元素和j出元素进行交换
rotate(List list, int distance):将所有元素向右移位指定长度,如果distance等于size那么结果不变

//查找和替换(主要针对Collection接口相关)
binarySearch(List list, Object key):使用二分搜索法,以获得指定对象在List中的索引,前提是集合已经排序
max(Collection coll):返回最大元素
max(Collection coll, Comparator comp):根据自定义比较器,返回最大元素
min(Collection coll):返回最小元素
min(Collection coll, Comparator comp):根据自定义比较器,返回最小元素
fill(List list, Object obj):使用指定对象填充
frequency(Collection Object o):返回指定集合中指定对象出现的次数
replaceAll(List list, Object old, Object new):替换

Stream数据流

主要是针对集合里数据进行分析处理。

而在Java类集中,由于其本身的作用就可以进行大量数据的存储,所以就顺其自然的产生了MapReduce操作,而这些操作可以通过Stream数据流来完成。

针对大数据问题,暂不考虑。

posted @ 2020-02-04 22:01  LampsAsarum  阅读(320)  评论(0编辑  收藏  举报