Java基础复习(七):集合

Java基础复习(七):集合

集合

在这里插入图片描述
Collection接口是所有单列集合的最顶层接口,List接口和Set接口分别实现了Collection接口;而我们常用的ArrayList集合、LinkedList集合等集合实现了List接口;常用的HashSet集合,LinkedHashSet集合等集合实现了Set接口。

1、Collection接口及常用方法:
    Collection接口是所有单列集合的最顶层接口,定义所有单列集合(即图片中最下层的所有集合)共性的方法:

public boolean add(E e):把给定的对象添加到当前的集合中
public void clear():清空集合所有的元素
public boolean remove(E e):把给定的对象从当前集合中删除
public boolean contains(E e):判断当前的集合中是否包含给定的对象
public boolean isEmpty():判断集合是否为空
public int size():返回集合中元素的个数
public Object[] toArray():把集合中的元素存放到数组中

2、List接口及常用方法:
    List接口的特点:
    集合中的元素有序、且可重复;
    集合中的每个元素都有其对应的顺序索引,容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素,并包含了一些带索引的方法。

public void add(int index, Object ele):将指定的元素添加在指定的索引位置(index)上
public boolean addAll(int index, Collection eles):在指定索引位置,加上一个集合
public Object get(int index):获取指定位置上的元素
public Object remove(int index):删除指定索引位置上的元素
public Object set(int index, Object ele):设置指定的索引位置(index)的位置的元素为ele
public int indexOf(Object obj):返回指定对象obj在集合中首次出现的位置,没有则返回-1public int lastIndexOf(Object obj):返回指定对象obj在集合最后一次出现的位置,没有则返回-1public List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex结束的子list,左闭右开的区间;

    (1)ArrayList:
    ArrayList是List接口的实现类,可以简单看作可变长度的数组。
    ArrayList的特点:1、ArrayList集合长度可变;2、线程不安全;3、查询效率高,增删效率低。
参考上述方法即可;4、底层为Object数组;

    (2)LinkedList:
    LinkedList也是List接口的实现类。
    LinkedList的特点:LinkedList底层是一个双向链表,查询慢,增删快;
    新增方法:

public void addFirst(E e):在列表的开头新增一个指定元素e
public void addLast(E e):在列表的最后位置新增一个指定元素e
public void push(E e):等效addFirst,将指定元素放入首位

public E getFirst():获取第一个元素
public E getLast():获取最后一个元素

public E removeFirst():删除第一个元素
public E removeLast():删除最后一个元素
public E pop():弹出列表最后一个元素
public boolean isEmpty():判断是否为空,如果为空,返回true
import java.util.LinkedList;

public class Test_LinkedList {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println("初始集合:");
        System.out.println(list);
        System.out.println("集合前放入0");
        list.addFirst(0);
        System.out.println(list);
        System.out.println("集合前放入-1");
        list.push(-1);
        System.out.println(list);
        System.out.println("取出第一个值:");
        System.out.println(list.pop());
        System.out.println("利用pop()弹出所有元素");
        while(list.isEmpty()!=true){
            System.out.println(list.pop());
        }

        System.out.println("最后的集合:"+list);
    }
}

结果:
初始集合:
[1, 2, 3]
集合前放入0
[0, 1, 2, 3]
集合前放入-1
[-1, 0, 1, 2, 3]
取出第一个值:
-1
利用pop()弹出所有元素
0
1
2
3
最后的集合:[]

    (3)Vector:
    Vector也是List接口的一个实现类。
    Vector的特点:1、vector底层是一个数组;2、增加同步检查,所以线程安全,但效率低;

3、Set接口及常用方法:
    Set接口的特点:1、不允许存储重复的元素(因为重写了equals方法和hashCode方法);
    (1)HashSet:
    HashSet的特点:1、不允许存储重复元素;2、是一个无序的集合,存储元素和取出元素的顺序可能不一致;3、底层是哈希表存储结构;4、允许使用null元素,但要保证元素的唯一性;

哈希表结构:
在这里插入图片描述
本质底层依赖两个方法:
int hashCode()
boolean equals(Object obj)

为什么重写equals的同时也要重写hashcode:
    因为在不重写equals时比较的是两个地址值;当重写了equals时,假设两个对象,重写了其equals方法,其相等条件是属性相等,就返回true。如果不重写hashcode方法,其返回的依然是两个对象的内存地址值,必然不相等。这就出现了equals方法相等,但是hashcode不相等的情况。这不符合hashcode的规则。重写equals()方法就必须重写hashCode()方法主要是针对HashSet和Map集合类型。集合框架只能存入对象(对象的引用(基本类型数据:自动装箱))。
    在向HashSet集合中存入一个元素时,HashSet会调用该对象(存入对象)的hashCode()方法来得到该对象的hashCode()值,然后根据该hashCode值决定该对象在HashSet中存储的位置。简单的说:HashSet集合判断两个元素相等的标准是:两个对象通过equals()方法比较相等,并且两个对象的HashCode()方法返回值也相等。如果两个元素通过equals()方法比较返回true,但是它们的hashCode()方法返回值不同,HashSet会把它们存储在不同的位置,依然可以添加成功。

    (2)LinkedHashSet:底层由哈希表+链表构成,由链表保证元素有序,由哈希表保证元素唯一。

4、Collections类的常用方法:

排序方法:
void reverse(List list)//反转
void shuffle(List list)//随机排序
void sort(List list)//按自然排序的升序排序
void sort(List list, Comparator c)//定制排序,由Comparator控制排序逻辑
void swap(List list, int i , int j)//交换两个索引位置的元素
void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面。

替换查找方法:
int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll)//根据元素的自然顺序,返回最大的元素。 类比int min(Collection coll)
int max(Collection coll, Comparator c)//根据定制排序,返回最大元素,排序规则由Comparatator类控制。类比int min(Collection coll, Comparator c)
void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素。
int frequency(Collection c, Object o)//统计元素出现次数
int indexOfSubList(List list, List target)//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List source, list target).
boolean replaceAll(List list, Object oldVal, Object newVal)// 用新元素替换旧元素

需要注意的是::
1、binarySearch()方法:默认的是集合是有序的,如果集合不是顺序排列,则有可能会找不到。

import java.util.ArrayList;
import java.util.Collections;

public class Test2_Collections {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(-1);
        arrayList.add(3);
        arrayList.add(3);
        arrayList.add(-5);
        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(-9);
        arrayList.add(-7);
        ArrayList<Integer> arrayList2 = new ArrayList<Integer>();
        arrayList2.add(-3);
        arrayList2.add(-5);
        arrayList2.add(7);
        System.out.println("原始数组:");
        System.out.println(arrayList);
        
        System.out.println("Collections.binarySearch(arrayList, 7):没排列的结果");
        System.out.println(Collections.binarySearch(arrayList, 7));

        System.out.println("Collections.binarySearch(arrayList, 7):升序排列后的结果");
        // 对List进行二分查找,返回索引,List必须是有序的
        Collections.sort(arrayList);//升序
        System.out.println(arrayList);
        System.out.println(Collections.binarySearch(arrayList, 7));
    }
}

结果:
原始数组:
[-1, 3, 3, -5, 7, 4, -9, -7]
Collections.binarySearch(arrayList, 7):没排列的结果
-9
Collections.binarySearch(arrayList, 7):升序排列后的结果
[-9, -7, -5, -1, 3, 3, 4, 7]
7

2、sort()方法:使用前提是,插入里面的元素必须实现Compareable,重写接口中的compareTo方法来自定义排序;一般常用的引用类型数据如:String类,自身含有CompareTo方法,所以直接引用就好;而其他的自定义类型就需要重写方法来实现。
(1)String 本身含有compareTo方法,所以可以直接调用sort方法,按自然顺序排序,即升序排序;
(2)调用sort(List list, Comparator c)方法,可以先实现Comparable接口新建一个比较类(例如:MyCompare类),将其传入sort方法中,按新类中的比较规则排序;
(3)用匿名内部类来实现MyCompare类的作用;
(4)传入对象已经实现了Comparable接口,有了compareTo方法;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Test_ComepareTo {
    public static void main(String[] args) {
        List<String> listS = new ArrayList<String>();
        List<Person1> list1 = new ArrayList<Person1>();
        List<Person2> list2 = new ArrayList<Person2>();
        List<Person3> list3 = new ArrayList<Person3>();

        //一.将String类型的变量插入到listS中并排序
        //listS中的对象String 本身含有compareTo方法,所以可以直接调用sort方法,按自然顺序排序,即升序排序
        listS.add("5");
        listS.add("2");
        listS.add("9");
        Collections.sort(listS);

        //二.将Person1类的对象插入到list1中并排序
        //将已创建的实现了Comparator接口的比较类MyCompare传入Collections的sort方法中即可实现依照MyCompare类中的比较规则。
        Person1 a1 = new Person1();
        Person1 b1 = new Person1();
        Person1 c1 = new Person1();
        a1.setName("a1");   a1.setAge(44);
        b1.setName("b1");   b1.setAge(55);
        c1.setName("b1");   c1.setAge(33);
        list1.add(a1);
        list1.add(b1);
        list1.add(c1);//Collections类的sort方法要求传入的第二个参数是一个已实现Comparator接口的比较器
        Collections.sort(list1, new MyCompare());

        //三.将Person2类的对象插入到list2中并排序
        //其实原理和上面的二类似,只是没有单独创建MyCompare类,而是用匿名内部类来实现Comparator接口里面的具体比较。
        Person2 a2 = new Person2();
        Person2 b2 = new Person2();
        Person2 c2 = new Person2();
        a2.setName("a2");   a2.setAge(66);
        b2.setName("b2");   b2.setAge(33);
        c2.setName("b2");   c2.setAge(22);
        list2.add(a2);
        list2.add(b2);
        list2.add(c2); //Collections类的sort方法要求传入的第二个参数是一个已实现Comparator接口的比较器
        Collections.sort(list2,new Comparator<Person2>(){
            @Override
            public int compare(Person2 a2, Person2 b2) {
                //a2.getOrder().compareTo(b2.getOrder()是升序排列的
                return a2.getOrder().compareTo(b2.getOrder());
            }

        });

        //四.将Person3类的对象插入到list3中并排序
        //被排序的类Person3实现了Comparable接口,在类Person3中通过重载compareTo方法来实现具体的比较,所以可以直接调用sort(List list)方法。
        Person3 a3 = new Person3();
        Person3 b3 = new Person3();
        Person3 c3 = new Person3();
        a3.setName("a3");   a3.setAge(77);
        b3.setName("b3");   b3.setAge(55);
        c3.setName("b3");   c3.setAge(99);
        list3.add(a3);
        list3.add(b3);
        list3.add(c3);
        Collections.sort(list3);//Collections类的sort方法要求传入的List中的对象是已实现Comparable接口的对象

        System.out.println(listS);
        System.out.println(list1);
        System.out.println(list3);
        System.out.println(list2);
    }
}
class Person1{
    private String name;
    private Integer age;
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override//重载了Object类里的toString方法,使之可以按照我们要求的格式打印
    public String toString() {
        return "name is "+name+" age is "+ age;
    }
}

class MyCompare implements Comparator<Person1> {
    @Override//重载了Comparator接口里面的compare方法实现具体的比较
    public int compare(Person1 o1, Person1 o2) {
        //一般o2-o1是降序,o1-o2是升序

//        return o2.getAge()-o1.getAge();//[name is b1 age is 55, name is a1 age is 44, name is b1 age is 33]
        return o1.getAge()-o2.getAge();//[name is b1 age is 33, name is a1 age is 44, name is b1 age is 55]
    }
}

class Person2{
    private String name;
    private Integer age;
    public void setName(String name) {
        this.name = name;
    }
    public Integer getOrder() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override//重载了Object类里的toString方法,使之可以按照我们要求的格式打印
    public String toString() {
        return "name is "+name+" age is "+age;
    }
}

class Person3 implements Comparable<Person3>{
    private String name;
    private Integer age;
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override//重载了Object类里的toString方法,使之可以按照我们要求的格式打印
    public String toString() {
        return "name is "+name+" age is "+age;
    }
    @Override//重载了Comparable接口里的compareTo方法来实现具体的比较
    public int compareTo(Person3 a) {
        return this.age.compareTo(a.getAge());
    }
}

结果:
[2, 5, 9]
[name is b1 age is 33, name is a1 age is 44, name is b1 age is 55]
[name is b3 age is 55, name is a3 age is 77, name is b3 age is 99]
[name is b2 age is 22, name is b2 age is 33, name is a2 age is 66]

而对于所有的排序方法,其实最后都要重写compareTo()方法。

其他方法:
emptyXxx(): 返回一个空的、不可变的集合对象,此处的集合既可以是List,也可以是Set,还可以是Map。
singletonXxx(): 返回一个只包含指定对象(只有一个或一个元素)的不可变的集合对象,此处的集合可以是:List,Set,Map。
unmodifiableXxx(): 返回指定集合对象的不可变视图,此处的集合可以是:List,Set,Map。
import java.util.*;
public class Test3_Collections {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(-1);
        arrayList.add(3);
        arrayList.add(3);
        arrayList.add(-5);
        arrayList.add(7);
        arrayList.add(4);
        arrayList.add(-9);
        arrayList.add(-7);
        HashSet<Integer> integers1 = new HashSet<>();
        integers1.add(1);
        integers1.add(3);
        integers1.add(2);
        Map scores = new HashMap();
        scores.put("语文" , 80);
        scores.put("Java" , 82);

        //Collections.emptyXXX();创建一个空的、不可改变的XXX对象
        List<Object> list = Collections.emptyList();
        System.out.println(list);//[]
        Set<Object> objects = Collections.emptySet();
        System.out.println(objects);//[]
        Map<Object, Object> objectObjectMap = Collections.emptyMap();
        System.out.println(objectObjectMap);//{}

        //Collections.singletonXXX();
        List<ArrayList<Integer>> arrayLists = Collections.singletonList(arrayList);
        System.out.println(arrayLists);//[[-1, 3, 3, -5, 7, 4, -9, -7]]
        //创建一个只有一个元素,且不可改变的Set对象
        Set<ArrayList<Integer>> singleton = Collections.singleton(arrayList);
        System.out.println(singleton);//[[-1, 3, 3, -5, 7, 4, -9, -7]]
        Map<String, String> nihao = Collections.singletonMap("1", "nihao");
        System.out.println(nihao);//{1=nihao}

        //unmodifiableXXX();创建普通XXX对象对应的不可变版本
        List<Integer> integers = Collections.unmodifiableList(arrayList);
        System.out.println(integers);//[-1, 3, 3, -5, 7, 4, -9, -7]
        Set<Integer> integers2 = Collections.unmodifiableSet(integers1);
        System.out.println(integers2);//[1, 2, 3]
        Map<Object, Object> objectObjectMap2 = Collections.unmodifiableMap(scores);
        System.out.println(objectObjectMap2);//{Java=82, 语文=80}
    }
}

结果:
[]
[]
{}
[[-1, 3, 3, -5, 7, 4, -9, -7]]
[[-1, 3, 3, -5, 7, 4, -9, -7]]
{1=nihao}
[-1, 3, 3, -5, 7, 4, -9, -7]
[1, 2, 3]
{Java=82, 语文=80}

引用文章:Collections类常用方法总结

5、Arrays类的常用方法:

排序 : sort()
sort(int[] a)//方法按照数字顺序排列指定的数组。
sort(int[] a,int fromIndex,int toIndex)//按升序排列数组的指定范围
parallelSort(int[] a)//按照数字顺序排列指定的数组(并行的)。同sort方法一样也有按范围的排序
查找 : binarySearch()
比较: equals()
填充 : fill()
转列表: asList()
转字符串 : toString()
复制: copyOf()
对字符串排序,依次比较每个字符:
String[] strs = { "abcdehg", "abcdefg", "abcdeag" };
Arrays.sort(strs);
System.out.println(Arrays.toString(strs));//[abcdeag, abcdefg, abcdehg]

6、Map<k,v>集合
    Map集合特点:(1)是一个双列集合,每一个元素包含两个值(键和值);(2)key和value的数据类型可以相同,可以不同;(3)key不允许重复,value可以重复;(4)key与value是一一对应的;

常用方法:
在这里插入图片描述
在这里插入图片描述
(1)HashMap:
     特点:(1)底层是一个哈希表,查询效率高;JDK1.8之前:数组+单向链表;JDK1.8之后:数组+单向链表/红黑树(链表长度超过8时)(2)是一个无序集合,存储和取出的顺序有可能不同;(3)key-value可以为null,但最多只能为一个null;(4)不支持线程同步,即可以有多个线程同时写HashMap,可能导致数据不一致,如果需要同步可以使用Collection的synchronizedMap方法使其同步。

(2)LinkedHashMap:
    特点:(1)底层是哈希表+链表;(2)是一个有序集合,存取顺序相同;

(3)遍历方法:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Test_Map {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "a");
        map.put(2, "b");
        map.put(3, "ab");
        map.put(4, "ab");
        map.put(4, "ab");
        System.out.println(map.size());

        /*
        1、调用keySet()方法,获取所有元素的key值,存入set集合
        2、遍历set集合,获取每一个key值
        3、通过get(key)获取value值
         */
        System.out.println("第一种:通过Map.keySet遍历key和value:");
        for (Integer in : map.keySet()) {
            //map.keySet()返回的是所有key值,并存放到一个set集合中,返回值为一个set集合
            String str = map.get(in);//得到每个key对应的value值
            System.out.println(in + "     " + str);
        }

        /*
        1、通过iterator()方法获取迭代器
        2、调用hasNext()判断有没有下一个元素,作为循环条件
        3、调用next()获取Map集合中的所有元素
        4、通过getKey()和getValue()分别取值
         */
        System.out.println("第二种:通过Map.entrySet使用iterator遍历key和value:");
        Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, String> entry = it.next();
            System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
        }

        /*
        1、调用entrySet()方法,获取到集合内多个entry对象存入set集合
        2、调用遍历set集合获取每个entry对象
        3、通过getKey()和getValue()分别取值
         */
        System.out.println("第三种:键值对,通过Map.entrySet遍历key和value");
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            //Map.entry<Integer,String> 映射项(键-值对)  有几个方法:用上面的名字entry
            //entry.getKey() ;entry.getValue(); entry.setValue();
            //map.entrySet()  返回此映射中包含的映射关系的 Set视图。
            System.out.println("key= " + entry.getKey() + " and value= "
                    + entry.getValue());
        }

        /*
        通过values()方法,但只能获取到value值,无法获取key值
         */
        System.out.println("第四种:通过Map.values()遍历所有的value,但不能遍历key");
        for (String v : map.values()) {
            System.out.println("value= " + v);
        }
    }
}

结果:
4
第一种:通过Map.keySet遍历key和value:
1 a
2 b
3 ab
4 ab
第二种:通过Map.entrySet使用iterator遍历key和value:
key= 1 and value= a
key= 2 and value= b
key= 3 and value= ab
key= 4 and value= ab
第三种:键值对,通过Map.entrySet遍历key和value
key= 1 and value= a
key= 2 and value= b
key= 3 and value= ab
key= 4 and value= ab
第四种:通过Map.values()遍历所有的value,但不能遍历key
value= a
value= b
value= ab
value= ab

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值