集合类

  • 为什么出现集合类?
    • 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
  • 数组和集合类同是容器,有何不同?
    • 数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
  • 集合类的特点
    • 集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

集合框架的构成及分类

ArrayList

底层的数据结构使用的是数组结构。线程不同步。

特点:因为该集合系有索引。

List接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括 null。除了实现List接口之外,此类还提供一些方法来操纵内部用于存储列表的数组的大小。(该类与Vector大致等效 ,但它是不同步的。)

size、isEmpty、get、set、iteratorlistIterator操作在常量时间内运行。添加操作在平摊常数时间内运行,即添加n个元素需要O(n)时间。所有其他操作都在线性时间内运行(粗略地说)。与LinkedList的实现相比,常数因子较低。

常用方法

增加元素

add()

将指定的元素追加到此列表的末尾。

public boolean add(E e)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // 创建一个集合容器。使用Collection接口的子类。ArrayList
        ArrayList al = new ArrayList();
        // 添加元素。
        al.add("Hello");
        al.add("World");
        al.add("ArrayList");
        // 输出集合
        // al = [Hello, World, ArrayList]
        System.out.println("al = " + al);
    }
}

清空和删除元素

remove()

从列表中删除指定元素的第一个出现(如果存在)。 如果列表不包含该元素,则它不会更改。 更正式地,删除具有最低索引i的元素,使得(o==null ? get(i)==null : o.equals(get(i))) (如果存在这样的元素)。 如果此列表包含指定的元素(或等效地,如果此列表作为调用的结果而更改),则返回true

public boolean remove(Object o)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // 创建一个集合容器。使用Collection接口的子类。ArrayList
        ArrayList al = new ArrayList();
        // 添加元素。
        al.add("Hello");
        al.add("World");
        al.add("ArrayList");
        // 删除元素
        al.remove("World");
        // al = [Hello, ArrayList]
        System.out.println("al = " + al);

    }
}
clear()

从列表中删除所有元素。 此呼叫返回后,列表将为空。

“`java
public void clear()
“`

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // 创建一个集合容器。使用Collection接口的子类。ArrayList
        ArrayList al = new ArrayList();
        // 添加元素。
        al.add("Hello");
        al.add("World");
        al.add("ArrayList");
        // 清空元素
        al.clear();
        // al = []
        System.out.println("al = " + al);
    }
}

修改

set()

用指定的元素替换此列表中指定位置的元素。

public E set(int index, E element)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        al.set(1, "item 4");
        // al = [item 1, item 4, item 3]
        System.out.println("al = " + al);
    }
}

获取

get()

返回此列表中指定位置的元素。

public E get(int index)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        // al.get(0) = item 1
        System.out.println("al.get(0) = " + al.get(0));
        // al.get(1) = item 2
        System.out.println("al.get(1) = " + al.get(1));
    }
}

判断元素

isEmpty()

如果此列表不包含元素,则返回 true

public boolean isEmpty()

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // 创建一个集合容器。使用Collection接口的子类。ArrayList
        ArrayList al = new ArrayList();
        // al.isEmpty() = true
        System.out.println("al.isEmpty() = " + al.isEmpty());
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        //al.isEmpty() = false
        System.out.println("al.isEmpty() = " + al.isEmpty());
    }
}

获取个数/长度。

size()

返回此列表中的元素数。

public int size()

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        // al.size() = 0
        System.out.println("al.size() = " + al.size());

        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        //al.size() = 3
        System.out.println("al.size() = " + al.size());

    }
}

去交集

retainAll()

仅保留此列表中包含在指定集合中的元素。 换句话说,从此列表中删除其中不包含在指定集合中的所有元素。

public boolean retainAll(Collection<?> c)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        ArrayList al1 = new ArrayList();
        al1.add("item 1");
        al1.add("item 4");
        al1.add("item 5");

        al.retainAll(al1);

        // al = [item 1]
        System.out.println("al = " + al);
        // al1 = [item 1, item 4, item 5]
        System.out.println("al1 = " + al1);
    }
}

删除相同

removeAll()

从此列表中删除指定集合中包含的所有元素。

public boolean removeAll(Collection<?> c)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        ArrayList al1 = new ArrayList();
        al1.add("item 1");
        al1.add("item 4");
        al1.add("item 5");

        al.removeAll(al1);

        // al = [item 2, item 3]
        System.out.println("al = " + al);
        // al1 = [item 1, item 4, item 5]
        System.out.println("al1 = " + al1);
    }
}

迭代器

其实就是集合的取出数据的方法。

一个集合的迭代器。Iterator需要的地方Enumeration在Java集合框架。迭代器有两种不同的枚举方式:

  • 迭代器允许调用者在迭代期间从底层集合中删除元素,并具有明确定义的语义。
  • 方法名称得到改进。

方法介绍

1. hasNext()

如果迭代具有更多的元素,则返回true (换句话说,如果next()返回一个元素而不是抛出一个异常,则返回true

boolean hasNext()

用法:

import java.util.ArrayList;
import java.util.Iterator;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        Iterator it = al.iterator();
        while (it.hasNext()){
            System.out.println("it.next() = " + it.next());
        }
    }
}

结果:

it.next() = item 1
it.next() = item 2
it.next() = item  3

2. next()

返回迭代中的下一个元素。

E next()

用法:

import java.util.ArrayList;
import java.util.Iterator;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        Iterator it = al.iterator();
        // it.next() = item 1
        System.out.println("it.next() = " + it.next());
        // it.next() = item 2
        System.out.println("it.next() = " + it.next());
        // it.next() = item 3
        System.out.println("it.next() = " + it.next());
        // Exception in thread "main" java.util.NoSuchElementException
        System.out.println("it.next() = " + it.next());
    }
}

3. remove()

从底层集合中删除此迭代器返回的最后一个元素(可选操作)。 此方法只能调用一次next() 。 如果底层集合在迭代过程中以任何方式进行修改而不是通过调用此方法,则迭代器的行为是未指定的。

default void remove()

用法:

import java.util.ArrayList;
import java.util.Iterator;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        Iterator it = al.iterator();
        // 获取第一个元素
        it.next();
        // 删除获取到的元素
        it.remove();
        // al = [item 2, item 3]
        System.out.println("al = " + al);
    }
}

迭代器内部实现

迭代器内部实现

ArrayList练习

需求:去除ArrayList集合的重复元素。

import java.util.ArrayList;
import java.util.Iterator;

public class Test {

    public static ArrayList singleElement(ArrayList arrayList) {
        ArrayList newAl = new ArrayList();

        Iterator it = arrayList.iterator();

        while (it.hasNext()) {
            Object obj = it.next();
            if (!newAl.contains(obj)) {
                newAl.add(obj);
            }
        }
        return newAl;
    }

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        al.add("item 1");
        al.add("item 2");

        // al = [item 1, item 2, item 3, item 1, item 2]
        System.out.println("al = " + al);
        // singleElement(al) = [item 1, item 2, item 3]
        System.out.println("singleElement(al) = " + singleElement(al));
    }
}

List

有序集合(也称为序列 )。该界面的用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。

特有方法

添加

add()

将指定的项目添加到滚动列表的末尾。

public void add(String item)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        al.add("item 4");
        al.add("item 5");
        // al = [item 1, item 2, item 3, item 4, item 5]
        System.out.println("al = " + al);

        al.add(1,"item 6");
        // al = [item 1, item 6, item 2, item 3, item 4, item 5]
        System.out.println("al = " + al);
    }
}
addAll()

按指定集合的迭代器(可选操作)返回的顺序将指定集合中的所有元素附加到此列表的末尾。 如果在操作进行中修改了指定的集合,则此操作的行为是未定义的。 (注意,如果指定的集合是此列表,并且它是非空的,则会发生这种情况。)

boolean addAll(Collection<? extends E> c)

将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。 将当前位于该位置(如果有的话)的元素和随后的任何元素移动到右边(增加其索引)。 新元素将按照指定集合的迭代器返回的顺序显示在此列表中。 如果在操作进行中修改了指定的集合,则此操作的行为是未定义的。 (注意,如果指定的集合是此列表,并且它是非空的,则会发生这种情况。)

boolean addAll(int index, Collection<? extends E> c)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");

        ArrayList al2 = new ArrayList();
        al2.add("item 4");
        al2.add("item 5");
        al2.add("item 6");

        al.addAll(al2);
        // al = [item 1, item 2, item 3, item 4, item 5, item 6]
        System.out.println("al = " + al);

        al.addAll(1, al2);
        // al = [item 1, item 4, item 5, item 6, item 2, item 3]
        System.out.println("al = " + al);
    }
}

删除

remove()

删除该列表中指定位置的元素(可选操作)。 将任何后续元素移动到左侧(从其索引中减去一个元素)。 返回从列表中删除的元素。

E remove(int index)

从列表中删除指定元素的第一个出现(如果存在)(可选操作)。 如果此列表不包含该元素,则它将保持不变。 更正式地,删除具有最低索引i的元素,使得(o==null ? get(i)==null : o.equals(get(i))) (如果这样的元素存在)。 如果此列表包含指定的元素(或等效地,如果此列表作为调用的结果而更改),则返回true

boolean remove(Object o)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        al.add("item 4");
        al.add("item 5");
        // al = [item 1, item 2, item 3, item 4, item 5]
        System.out.println("al = " + al);

        al.remove(2);
        // al = [item 1, item 2, item 4, item 5]
        System.out.println("al = " + al);
    }
}

修改

set()

用指定的元素(可选操作)替换此列表中指定位置的元素。

E set(int index, E element)

参数:

  • index 要替换的元素索引。
  • element 要替换在指定位置的元素。

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        al.add("item 4");
        al.add("item 5");
        // al = [item 1, item 2, item 3, item 4, item 5]
        System.out.println("al = " + al);

        al.set(1, "item 6");
        // al = [item 1, item 6, item 3, item 4, item 5]
        System.out.println("al = " + al);
    }
}

查询

get()

返回此列表中指定位置的元素。

E get(int index)

用法:

// 获取全部数据可以使用遍历来获取数据。
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        al.a add("item 5");
        // al = [item 1, item 2, item 3, item 4, item 5]
        System.out.println("al = " + al);
        // al.get(1) = item 2
        System.out.println("al.get(1) = " + al.get(1));
    }
}
subList()

返回列表中指定的fromIndex (含)和toIndex之间的部分视图。 (如果fromIndextoIndex相等,返回的列表为空。)返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。 返回的列表支持此列表支持的所有可选列表操作。

List<E> subList(int fromIndex, int toIndex)

参数:

  • fromIndex 低端点(含)。
  • toIndex 高端点(排他)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        // al.subList(0,2) = [item 2]
        System.out.println("al.subList(1,2) = " + al.subList(1, 2));
    }
}
indexOf()

返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。 更正式地,返回最低指数i ,使(o==null ? get(i)==null : o.equals(get(i))) ,或-1如果没有这样的指数。

int indexOf(Object o)

用法:

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        // al.indexOf("item 2") = 1
        System.out.println("al.indexOf(\"item 2\") = " + al.indexOf("item 2"));
        // al.indexOf("item 4") = -1
        System.out.println("al.indexOf(\"item 4\") = " + al.indexOf("item 4"));
    }
}
listIterator()

ListIteratoriterator的子接口。

在迭代时,不可以通过集合对象的方法操作集合中的元素。

因为会发送ConcurrentModificationException异常,所以在迭代器时,只能用迭代器的放过操作元素,可以时Iteration方法是有限的,只要对元素进行判断,取出,删除操作,

如果想要其他操作如添加,修改等,就需要使用其子接口,ListIterator,就接口只能通过List集合的ListIterator方法获取。

用法:

// 在迭代过程中,判断迭代的数据是否等于item 2,如果等于就添加一个item 4。
import java.util.ArrayList;
import java.util.ListIterator;

public class Test {
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("item 1");
        al.add("item 2");
        al.add("item 3");
        // al = [item 1, item 2, item 3]
        System.out.println("al = " + al);

        ListIterator li = al.listIterator();
        while (li.hasNext()) {
            Object obj = li.next();
            if (obj.equals("item 2")) {
                li.add("item 4");
            }
        }
        // al = [item 1, item 2, item 4, item 3]
        System.out.println("al = " + al);

    }
}

LinkedList

底层使用的链表数据结构。

特点:增删速度很快,查询稍慢。

import java.util.LinkedList;

/**
 * LinkedList:特有方法:
 * addFirst();
 * addLast();
 *
 * getFirst();
 * getLast();
 * // 获取元素,但不删除元素,如果集合中没有元素,会出现NoSuchElementException。
 *
 * removeFirst();
 * removeLast();
 * 获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException。
 *
 * 在JDK1.6出现了替代方法。
 * 
 * offerFirst();
 * offerLast();
 * 添加元素
 *
 * peekFirst();
 * peekLast();
 * 获取元素,但不删除元素。如果集合中没有元素,会返回null。
 *
 * pollFirst();
 * pollLast();
 * 获取元素,但是元素被删除。如果集合中没有元素,会返回null。
 */
public class Test {
    public static void main(String[] args) {
        LinkedList link = new LinkedList();
        link.addFirst("item 1");
        link.addFirst("item 2");
        link.addFirst("item 3");
        // link = [item 3, item 2, item 1]
        System.out.println("link = " + link);
        // link.getFirst() = item 3
        System.out.println("link.getFirst() = " + link.getFirst());
        // link.getLast() = item 1
        System.out.println("link.getLast() = " + link.getLast());
        link.removeFirst();
        // link = [item 2, item 1]
        System.out.println("link = " + link);
        link.removeLast();
        // link = [item 2]
        System.out.println("link = " + link);


    }
}

练习

使用LinkedList模拟堆栈模式

堆栈:先进后出,如同杯子的水。

import java.util.LinkedList;

class DuiLie {
    private LinkedList link;

    DuiLie() {
        link = new LinkedList();
    }

    public void myAdd(Object obj) {
        link.addFirst(obj);
    }

    public Object myGet() {
        return link.removeLast();
    }

    public boolean isNull() {
        return link.isEmpty();
    }
}

public class Test {
    public static void main(String[] args) {
        DuiLie dl = new DuiLie();
        dl.myAdd("item 1");
        dl.myAdd("item 2");
        dl.myAdd("item 3");
    }
}

使用LinkedList模拟队列模式

队列:先进先出,First in Fist out FIFO 如同一个水管

import java.util.LinkedList;

class DuiLie {
    private LinkedList link;

    DuiLie() {
        link = new LinkedList();
    }

    public void myAdd(Object obj) {
        link.addFirst(obj);
    }

    public Object myGet() {
        return link.removeFirst();
    }

    public boolean isNull() {
        return link.isEmpty();
    }
}

public class Test {
    public static void main(String[] args) {
        DuiLie dl = new DuiLie();
        dl.myAdd("item 1");
        dl.myAdd("item 2");
        dl.myAdd("item 3");
    }
}

Vector

底层数组数据结构。线程是同步的。ArrayList替代了。

用法:

import java.util.Enumeration;
import java.util.Vector;
/**
 * 枚举就是Vector特有的取出方式。
 * 发现枚举和迭代器很像。
 * 其实枚举和迭代时一样。
 * 
 * 因为枚举的名称以方法的名称都过长,所以被迭代器取代。
 * 枚举郁郁而终。
 */
public class Test {
    public static void main(String[] args) {
        Vector v = new Vector();

        v.add("item 1");
        v.add("item 2");
        v.add("item 3");

        Enumeration en = v.elements();
        while (en.hasMoreElements()){
            System.out.println("en.nextElement() = " + en.nextElement());
        } 

    }
}

Set

不包含重复元素的集合。更正式地,集合不包含一对元素e1e2 ,使得e1.equals(e2) ,并且最多一个空元素。正如其名称所暗示的那样,这个接口模拟了数学抽象。

HashSet:

此类实现Set接口,由哈希表(实际为HashMap实例)支持。对集合的迭代次序不作任何保证;特别是,它不能保证订单在一段时间内保持不变。这个类允许null元素。

保证元素唯一性的原理:判断元素的hashCode值是否相同。

如果相同,还会继续判断元素的equals方法,是否为true

用法:

public class Test {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        hs.add("item 1");
        hs.add("item 2");
        hs.add("item 3");
        // hs = [item 3, item 2, item 1]
        System.out.println("hs = " + hs);

        Iterator it = hs.iterator();
        while (it.hasNext()) {
            System.out.println("it.next() = " + it.next());
        }
    }
}
  • HashSet是如何保证元素唯一性的呢?
    • 是通过元素的两个方法,hasCodeequals来完成。
    • 如果元素的HashCode值相同,才会判断equals是否为true
  • 如果元素的hashcode值不同,不会调用equals
    • 注意:对于判断元素是否存在,以及删除操作,依赖的方法是元素的hashcodeequals方法。
import java.util.HashSet;
import java.util.Iterator;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int hashCode() {
        return name.hashCode() + age * 2;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Person)) {
            return false;
        }

        Person p = (Person) obj;
        return this.name.equals(p.name) && this.age == p.age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class Test {
    public static void main(String[] args) {
        HashSet hs = new HashSet();
        hs.add(new Person("a1", 13));
        hs.add(new Person("a2", 16));
        hs.add(new Person("a3", 15));
        hs.add(new Person("a3", 15));

        Iterator it = hs.iterator();
        while (it.hasNext()) {
            Person p = (Person) it.next();
            System.out.println("name:" + p.getName() + " - " + "age:" + p.getAge());
        }
    }
}

结果:

name:a1 - age:13
name:a2 - age:16
name:a3 - age:15

TreeSet

可以对Set集合中的元素进行排序。

底层数据结构是二叉树。

保证元素的唯一性的依据。

compareTo方法return 0;

用法:

import java.util.Iterator;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();
        ts.add("item 1");
        ts.add("item 2");
        ts.add("item 3");
        ts.add("item 5");
        ts.add("item 4");
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            System.out.println("it.next() = " + it.next());
        }
    }
}

结果:

it.next() = item 1
it.next() = item 2
it.next() = item 3
it.next() = item 4
it.next() = item 5

练习

TreeSet排序的第一次方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。

也种方式也成为元素的自然顺序,或者叫做默认顺序。

  • 储存自定义对象
/**
 * 往TreeSet集合中储存自定义对象学生。
 * 想按照学生的年龄进行排序。
 *
 * 记住,排序时,当主要条件相同时,一定要判断一下次要条件。 */

import java.util.Iterator;
import java.util.TreeSet;

class Student implements Comparable {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int compareTo(Object o) {
        if (!(o instanceof Student)) {
            throw new RuntimeException("不是学生对象");
        }
        Student s = (Student) o;
        if (this.age > s.age) {
            return 1;
        }
        if (this.age == s.age) {
            return this.name.compareTo(s.name);
        }
        return -1;
    }
}

public class Test {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();
        ts.add(new Student("lishi01", 20));

        ts.add(new Student("lishi03", 22));
        ts.add(new Student("lishi04", 23));
        ts.add(new Student("lishi02", 21));
        ts.add(new Student("lishi05", 24));
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            Student student = (Student) it.next();
            System.out.println("student.getName() = " + student.getName());
        }
    }
}
  • 定义一个类,实现Comparator接口,覆盖compare方法。

TreeSet排序的第二种方式:当元素自身不具备比较性,或者具备的比较性不是所需要的。

这时就需要让集合自身具备比较性。

在集合初始化时,就有了比较方式。

/**
 * 当元素自身不具备比较性,或者具备的比较性不是所需要的。
 * 这时需要让容器自身具备比较性。
 * 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
 * 当两个排序都存在时,以比较器为主。
 */
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

}

public class Test {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new MyConpare());
        ts.add(new Student("lishi01", 20));

        ts.add(new Student("lishi03", 22));
        ts.add(new Student("lishi05", 24));
        ts.add(new Student("lishi04", 23));
        ts.add(new Student("lishi02", 21));
        ts.add(new Student("lishi02", 20));
        Iterator it = ts.iterator();
        while (it.hasNext()) {
            Student student = (Student) it.next();
            System.out.println("student.getName() = " + student.getName());
        }
    }
}

class MyConpare implements Comparator {

    @Override
    public int compare(Object o1, Object o2) {
        Student s1 = (Student) o1;
        Student s2 = (Student) o2;

        int num = s1.getName().compareTo(s2.getName());
        if (num == 0) {
            return Integer.compare(s1.getAge(), s2.getAge());
        }
        return num;
    }
}
  • 按照字符串长度排序。
package com.company;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;


public class Test {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new StrLenComparator());
        ts.add("1");
        ts.add("12345");
        ts.add("12");
        ts.add("123");
        ts.add("1234");

        Iterator it = ts.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println("s = " + s);
        }
    }
}

class StrLenComparator implements Comparator {

    @Override
    public int compare(Object o1, Object o2) {
        String s1 = (String) o1;
        String s2 = (String) o2;
        int num = Integer.compare(s1.length(), s2.length());
        if (num == 0) {
            return s1.compareTo(s2);
        }
        return num;
    }
}

结果:

s = 1
s = 12
s = 123
s = 1234 
s = 12345

泛型

JDK1.5版本以后出现新特性。用于解决安全问题,是一个安全机制。

好处:

  1. 将运行时期出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题。让运行事情问题减少,安全。
  2. 避免了强制转换类型麻烦。

格式

通过<>来定义要操作的引用数据类型。

在使用java提供的对象时,什么时候写泛型呢?

通常在集合框架中很常见。只要见到<>就要定义泛型。

对象<类型> 变量名 = new 对象<类型>();

练习:

  • 使用泛型,根据字符串长度来排序。
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        TreeSet<String> ts = new TreeSet<>(new LenComparator());
        ts.add("item 22");
        ts.add("item 1");
        ts.add("item 333");

        Iterator<String> it = ts.iterator();

        while (it.hasNext()) {
            System.out.println("it.next() = " + it.next());
        }
    }
}

class LenComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        int num = Integer.compare(o1.length(), o2.length());
        if (num == 0) {
            return o1.compareTo(o2);
        }
        return num;
    }
}

泛型类

什么时候定义泛型类?

当类中要操作引用数据类型不确定的时候。

早期定义Object来完成扩展。

现在定义泛型来完成扩展。

package com.company;

class Worker { }

class Student { }

/**
 * 泛型前的做法
 */
class Tool {
    private Object obj;

    public void setObject(Object obj) {
        this.obj = obj;
    }

    public Object getObject() {
        return this.obj;
    }
}

/**
 * 泛型类
 *
 * @param <QQ>
 */
class Utils<QQ> {
    private QQ q;

    public void setQ(QQ q) {
        this.q = q;
    }

    public QQ getQ() {
        return this.q;
    }
}

public class Test {
    public static void main(String[] args) {
        Tool t = new Tool();
        t.setObject(new Worker());
        Worker w = (Worker) t.getObject();

        Utils<Worker> u = new Utils<Worker>();
        u.setQ(new Worker());
        Worker q = u.getQ();
    }
}

泛型方法:

泛型类定义的泛型,在整个类中有效。如果被方法使用。

那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。

class Demo<T> {
    public void show(T t) {
        System.out.println("show:" + t);
    }

    public void print(T t) {
        System.out.println("print:" + t);
    }
}

public class Test {
    public static void main(String[] args) {
        Demo<String> d = new Demo<>();
        // show:haha
        d.show("haha");
        // print:hehe
        d.print("hehe");
    }
}

为了让不同方法可以操作不同类型,而且类型还不确定。

那么可以将泛型定义在方法上。

class Demo {
    public <T> void show(T t) {
        System.out.println("show:" + t);
    }

    public <Q> void print(Q q) {
        System.out.println("print:" + q);
    }

    public static <W> void method(W w) {
        System.out.println("method:" + w);
    }
}


public class Test {
    public static void main(String[] args) {
        Demo d = new Demo();
        // show:199
        d.show(new Integer(199));
        // print:hehe
        d.print("hehe");
        // method:true
        Demo.method(true);
    }
}

泛型接口

interface Inter<T> {
    void show(T t);
}

class InterImpl<T> implements Inter<T> {

    @Override
    public void show(T t) {
        System.out.println("show:" + t);
    }
}

public class Test {
    public static void main(String[] args) {
        InterImpl<Integer> i = new InterImpl<>();
        // show:111
        i.show(111);
    }
}

泛型限定

/**
 * ? 通配符。也可以理解为占位符。
 * 泛型的限定:
 * ? extends E:可以接收E类型或者E的子类型。上限。
 * ? super E:可以接收E类型或者E的父类型。下限
 */

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

class Person {
    private String name;

    Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Student extends Person implements Comparable<Person> {

    Student(String name) {
        super(name);
    }

    @Override
    public int compareTo(Person o) {
        return 0;
    }
}

class Comp implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

public class Test1 {
    public static void main(String[] args) {
        ArrayList<Person> al = new ArrayList<>();
        al.add(new Person("abc"));
        al.add(new Person("efg"));
        al.add(new Person("hij"));

        ArrayList<Person> al1 = new ArrayList<>();
        al1.add(new Student("abc1"));
        al1.add(new Student("efg1"));
        al1.add(new Student("hij1"));

        TreeSet<Student> ts = new TreeSet<>();
        ts.add(new Student("abcs"));
        ts.add(new Student("abcs"));
        ts.add(new Student("abcs"));
    }

    // 上限
    public static void printColl(ArrayList<? extends Person> al) {
        Iterator<? extends Person> it = al.iterator();
        while (it.hasNext()) {
            System.out.println(it.next().getName());
        }
    }

    // 下限
    public static void printColl1(ArrayList<? super Student> al) {
        Iterator<? super Student> it = al.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

Map

将键映射到值的对象。 地图不能包含重复的键; 每个键可以映射到最多一个值。

特点:

  • 该集合储存键值对。

  • 一对一对往里存。

  • 而且要保证键的唯一性。

语法:

public interface Map<K,V>

参数:

  • K 由此地图维护的键类型。
  • V 映射的类型。

用法:

方法:

1.添加

put()

将指定的值与该映射中的指定键相关联(可选操作)。 如果映射先前包含了密钥的映射,则旧值将被指定的值替换。 (映射m被认为包含关键字的映射k当且仅当m.containsKey(k)将返回true )。

V put(K key, V value)

参数:

  • key 指定值与子关联的键。
  • value 与指定相关的值。

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        // 添加元素
        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
    }
}

2.删除

clear()

从该Map中删除所有的映射(可选操作)。 返回后,Map将为空。

void clear()

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        // map = {01=zhangsan1, 02=zhangsan2, 03=zhangsan3}
        System.out.println("map = " + map);
        map.clear();
        // map = {}
        System.out.println("map = " + map);

    }
}
remove()

如果存在(从可选的操作),从该地图中删除一个键的映射。 更正式地,如果该映射包含从关键字k到值v的映射,使得(key==null ? k==null : key.equals(k)) ,该映射被去除。

V remove(Object key)

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        // map.remove("02") = zhangsan2
        System.out.println("map.remove(\"02\") = " + map.remove("02"));
        // map.remove("02") = null
        System.out.println("map.remove(\"02\") = " + map.remove("02"));
        // map.remove("05") = null
        System.out.println("map.remove(\"05\") = " + map.remove("05"));

        // map.remove("01","zhangsan1") = true
        System.out.println("map.remove(\"01\",\"zhangsan1\") = " + map.remove("01", "zhangsan1"));
        // map.remove("03","zhangsan1") = false
        System.out.println("map.remove(\"03\",\"zhangsan1\") = " + map.remove("03", "zhangsan1"));
        // map.remove("03","zhangsan3") = true
        System.out.println("map.remove(\"03\",\"zhangsan3\") = " + map.remove("03", "zhangsan3"));
    }
}

3.判断

containsValue()

如果此映射将一个或多个键映射到指定的值,则返回true 更正式地,返回true当且仅当此映射包含至少一个映射到值v ,使得(value==null ? v==null : value.equals(v)) 。 对于Map接口的大多数实现,此操作对于Map大小可能需要时间线性。

boolean containsValue(Object value)

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("01", "zhangsan1");
        map.put("04", "zhangsan1");
        map.put("05", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        // map.containsValue("zhangsan1") = true
        System.out.println("map.containsValue(\"zhangsan1\") = " + map.containsValue("zhangsan1"));
        // map.containsValue("zhangsan2") = true
        System.out.println("map.containsValue(\"zhangsan2\") = " + map.containsValue("zhangsan2"));
        // map.containsValue("zhangsan4") = false
        System.out.println("map.containsValue(\"zhangsan4\") = " + map.containsValue("zhangsan4"));
    }
}
containsKey()

如果此映射包含指定键的映射,则返回true 更正式地,返回true当且仅当该地图包含关键字k的映射,使得(key==null ? k==null : key.equals(k)) 。 (最多可以有一个这样的映射。)

boolean containsKey(Object key)

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        // 添加元素
        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        // map.containsKey("01") = true
        System.out.println("map.containsKey(\"01\") = " + map.containsKey("01"));
        // map.containsKey("03") = true
        System.out.println("map.containsKey(\"03\") = " + map.containsKey("03"));
        // map.containsKey("04") = false
        System.out.println("map.containsKey(\"04\") = " + map.containsKey("04"));
    }
}
isEmpty()

如果此Map不包含键值映射,则返回 true

boolean isEmpty()

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        // map.isEmpty() = false
        System.out.println("map.isEmpty() = " + map.isEmpty());

        HashMap<String, String> map1 = new HashMap<>();
        // map1.isEmpty() = true
        System.out.println("map1.isEmpty() = " + map1.isEmpty());
    }
}

4.获取

get()

返回到指定键所映射的值,或null如果此映射包含该键的映射。

V get(Object key)

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");

        map.put("04", null);

        // map.get("02") = zhangsan2
        System.out.println("map.get(\"02\") = " + map.get("02"));
        // map.get("04") = null
        System.out.println("map.get(\"04\") = " + map.get("04"));
        // map.get("05") = null
        System.out.println("map.get(\"05\") = " + map.get("05"));
    }
}
size()

返回此Map中键值映射的数量。 如果Map包含超过Integer.MAX_VALUE个元素,则返回Integer.MAX_VALUE

int size()

用法:

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        // map.size() = 3
        System.out.println("map.size() = " + map.size());
    }
}
values()

返回此地图中包含的值的Collection视图。 集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行中修改映射(除了通过迭代器自己的remove操作),迭代的结果是未定义的。 该collection支持元素移除,即从映射中相应的映射,经由Iterator.remove,Collection.remove,removeAll,retainAllclear操作。 它不支持addaddAll操作。

Collection<V> values()

用法:

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        map.put("01", "zhangsan1");
        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");

        map.put("04", null);

        Collection<String> coll = map.values();
        // coll = [zhangsan1, zhangsan2, zhangsan3, null]
        System.out.println("coll = " + coll);
    }
}
entrySet()

返回此Map中包含的映射的Set视图。 该集合由Map支持,因此对Map的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改映射(除了通过迭代器自己的remove操作,或者通过迭代器返回的映射条目上的setValue操作),迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.remove,Set.remove,removeAll,retainAllclear操作。 它不支持addaddAll操作。

Set<Map.Entry<K,V>> entrySet()

用法:

import java.util.*;

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        map.put("01", "zhangsan1");
        // 就Map集合中的映射关系取出。存入到Set集合中。
        Set<Map.Entry<String, String>> entrySet = map.entrySet();

        Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            System.out.println(next.getKey() + " - " + next.getValue());
        }
    }
}
keySet()

返回此map中包含的键的Set视图。 该集合由map支持,因此对map的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行中修改映射(除了通过迭代器自己的remove操作),迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.remove,Set.remove,removeAll,retainAllclear操作。 它不支持addaddAll操作。

Set<K> keySet()

用法:

import java.util.*;

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        map.put("02", "zhangsan2");
        map.put("03", "zhangsan3");
        map.put("01", "zhangsan1");
        // 先获取Map集合的所有键的Set集合,keySet();
        Set<String> keySet = map.keySet();
        // 有了Set集合。就可以获取其迭代器。
        Iterator<String> it = keySet.iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = map.get(key);
            System.out.println("key=" + key + ",value=" + value);
        }
    }
}

练习

  • 练习一
package com.company;

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

/**
 * 每一个学生都有对应的归属地。
 * 学生Student,地址String。
 * 学生属性:姓名,年龄
 * 注意:姓名和年龄相同的视为同一个学生。
 * 保证学生的唯一性。
 * <p>
 * 1.描述学生。
 * 2.定义map容器。将学生做为键,地址作为值,存入。
 * 3.获取map集合中的元素。
 */

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int hashCode() {
        return this.name.hashCode() + age * 2;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Student)) {
            throw new ClassCastException("类型不匹配");
        }
        Student s = (Student) obj;
        return this.name.equals(s.name) && this.age == s.age;
    }

    @Override
    public String toString() {
        return this.name + " - " + this.age;
    }

    @Override
    public int compareTo(Student o) {
        int num = Integer.compare(this.age, o.age);
        if (num == 0) {
            return 0;
        }
        return num;
    }
}

public class MapDemo {
    public static void main(String[] args) {
        HashMap<Student, String> hm = new HashMap<>();
        hm.put(new Student("lishi", 11), "beijing");
        hm.put(new Student("zhangsan", 21), "shanghai");

        // 第一种取出方式:keySet
        Iterator<Student> it = hm.keySet().iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        // 第二种取出方式:entrySet
        Iterator<Map.Entry<Student, String>> iterator = hm.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Student, String> next = iterator.next();
            System.out.println(next);
        }
    }
}
  • 练习二:
package com.company;

/**
 * 需求:对学生对象的年龄进行升序排序。
 * <p>
 * 因为数据是以键值形式存在的,所有要使用可以排序的Map集合。TreeMap
 */

import java.util.*;

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

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int hashCode() {
        return this.name.hashCode() + age * 2;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Student)) {
            throw new ClassCastException("类型不匹配");
        }
        Student s = (Student) obj;
        return this.name.equals(s.name) && this.age == s.age;
    }

    @Override
    public String toString() {
        return this.name + " - " + this.age;
    }

    @Override
    public int compareTo(Student o) {
        int num = Integer.compare(this.age, o.age);
        if (num == 0) {
            return 0;
        }
        return num;
    }
}

class StuNameComparaor implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        int num = o1.getName().compareTo(o2.getName());
        if (num == 0) {
            return Integer.compare(o1.getAge(), o2.getAge());
        }
        return num;
    }
}

public class MapDemo {
    public static void main(String[] args) {
        TreeMap<Student, String> tm = new TreeMap<>();
        tm.put(new Student("lishi3", 23), "nanjing");
        tm.put(new Student("lishi2", 21), "beijing");
        tm.put(new Student("lishi1", 25), "wuhan");

        Iterator<Map.Entry<Student, String>> it = tm.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Student, String> me = it.next();
            Student stu = me.getKey();
            String addr = me.getValue();
            System.out.println(stu + " - " + addr);
        }
    }
}
  • 练习三
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * sdfgzxcvasdfxcvdf 获取该字符串种的字母出现的次数。
 * 希望输出结果:a(1)c(2)...
 * 
 * 通过结果发现,每一个字母都有对应次数。
 * 说明字母和次数之间都有映射关系。
 * 
 * 注意了。当发现有映射关系时,可以选择Map集合。
 * 因为Map集合种存放就是映射关系。
 * 
 * 什么时候使用Map集合呢?
 * 当数据之间存在这映射关系时,就要先想Map集合。
 * 
 * 思路:
 * 1.将字符串转换字符数组,因为要对每一个字母进行操作。
 * 2.定义一个Map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。
 * 3.遍历字符串数组。
 *  将每一个字母作为键去查Map集合。
 *  如果返回null,就该字母和1存入到map集合中。
 *  如果返回不是null,说明该字母在Map集合已经存在并有对应次数。
 *  那么就获取该次数并进行自增。然后将该字母和自增后的次数存入到Map集合中。覆盖调用原理键所对应的值。
 * 
 * 4.将Map集合中的数据变成指定的字符串形式返回。
 */

public class MapDemo {
    public static void main(String[] args) {
        System.out.println(charCount("sdfgzxcvasdfxcvdf"));
    }

    public static String charCount(String str) {
        char[] chs = str.toCharArray();
        TreeMap<Character, Integer> tm = new TreeMap<>();
        int count = 0;
        for (int i = 0; i < chs.length; i++) {
            if (!(chs[i] >= 'a' && chs[i] <= 'z' && chs[i] >= 'A' && chs[i] <= 'Z')) {
                continue;
            }

            Integer value = tm.get(chs[i]);
            if (value != null) {
                count = value;
            }
            count++;
            tm.put(chs[i], count);
            count = 0;
        }

        StringBuilder sb = new StringBuilder();
        Iterator<Map.Entry<Character, Integer>> it = tm.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Character, Integer> me = it.next();
            Character key = me.getKey();
            Integer value = me.getValue();
            sb.append(key + "(" + value + ")");
        }

        return sb.toString();
    }
}

HashTable

特点:

  • 底层是哈希表数据结构,不可以存入null键null值
  • 该集合是线程同步。
  • jdk1.0 效率低。

HashMap

特点:

  • 底层是哈希表数据结构,允许使用null键和null值。
  • 该集合是线程不同步。
  • jdk1.2 效率高。

TreeMap

特点:

  • 底层是二叉树数据结构。
  • 该集合线程不同步。
  • 可以用于给map集合中的键进行排序。

Collections

此类仅由静态方法组合或返回集合。它包含对集合进行操作的多态算法,“包装器”,返回由指定集合支持的新集合,以及其他一些可能的和最终的。

如果提供给它们的集合或类对象为null,则此类的方法都抛出一个NullPointerException

常用方法:

sort()

根据指定的比较器引起的顺序对指定的列表进行排序。 列表中的所有元素必须使用指定的比较器相互比较 (即, c.compare(e1, e2)不能为ClassCastException中的任何元素e1e2 )。

public static <T> void sort(List<T> list, Comparator<? super T> c)

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        sortDemo();
    }

    public static void sortDemo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("d122f");
        list.add("122");
        list.add("1dfas22");
        list.add("1dfas22");
        list.add("d12d2");
        list.add("12df2");
        // [d122f, 122, 1dfas22, 1dfas22, d12d2, 12df2]
        System.out.println(list);
        Collections.sort(list);
        // [122, 12df2, 1dfas22, 1dfas22, d122f, d12d2]
        System.out.println(list);
    }
}

练习:

/**
 * 根据字符串长度来排序
 */

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

public class CollectionsDemo {
    public static void main(String[] args) {
        sortDemo();
    }

    public static void sortDemo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("d122f");
        list.add("122");
        list.add("1dfas22");
        list.add("1dfas22");
        list.add("d12d2");
        list.add("12df2");
        // [d122f, 122, 1dfas22, 1dfas22, d12d2, 12df2]
        System.out.println(list);

        Collections.sort(list, new StrLenComparator());
        // [122, d122f, d12d2, 12df2, 1dfas22, 1dfas22]
        System.out.println(list);
    }

}

class StrLenComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        int num = Integer.compare(o1.length(), o2.length());
        if (num == 0) {
            return 0;
        }
        return num;
    }
}

max()

根据指定的比较器引发的顺序返回给定集合的最大元素。集合中的所有元素必须由指定的比较器相互比较 (即, comp.compare(e1, e2)不得为集合中的任何元素e1e2投放ClassCastException)。

该方法遍历整个集合,因此它需要与集合的大小成比例的时间。

public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)

参数:

  • coll 要确定其最大值的集合。
  • comp 用于确定最大比较器。

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        maxDemo();
    }

    public static void maxDemo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("5");
        list.add("10");
        list.add("1");
        list.add("133");
        list.add("231");
        list.add("2");
        // list = [5, 10, 1, 133, 231, 2]
        System.out.println("list = " + list);
        // Collections.max(list) = 5
        System.out.println("Collections.max(list) = " + Collections.max(list));
        // 根据字符串长度来获取
        // Collections.max(list,new StrLenComparator()) = 133
        System.out.println("Collections.max(list,new StrLenComparator()) = " + Collections.max(list, new StrLenComparator()));
    }
}

class StrLenComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        int compare = Integer.compare(o1.length(), o2.length());
        if (compare == 0) {
            return 0;
        }
        return compare;
    }
}

binarySearch()

使用二叉搜索算法搜索指定对象的指定列表。 该列表必须根据被按升序排列natural ordering元素(如由sort(List)方法)之前使该呼叫。 如果没有排序,结果是未定义的。 如果列表包含与指定对象相等的多个元素,则不能保证将找到哪个元素。

public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        binarySearchDemo();
    }

    public static void binarySearchDemo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("5");
        list.add("10");
        list.add("1");
        list.add("133");
        list.add("231");
        list.add("2");
        // list = [5, 10, 1, 133, 231, 2]
        System.out.println("list = " + list);
        Collections.sort(list);
        // list = [1, 10, 133, 2, 231, 5]
        System.out.println("list = " + list);
        // i = 2
        int i = Collections.binarySearch(list, "133");
        System.out.println("i = " + i);
    }
}

fill()

用指定的元素代替指定列表的所有元素。 该方法运行在线性时间。

public static <T> void fill(List<? super T> list, T obj)

参数:

  • list 要填充指定元素的列表。
  • obj 用于填充指定列表的元素。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class CollectionsDemo {
    public static void main(String[] args) {
        fillDemo();
    }

    public static void fillDemo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("5");
        list.add("10");
        list.add("1");
        list.add("133");
        list.add("231");
        list.add("2");
        // list = [5, 10, 1, 133, 231, 2]
        System.out.println("list = " + list);
        Collections.fill(list,"6");
        // list = [6, 6, 6, 6, 6, 6]
        System.out.println("list = " + list);

    }
}

replaceAll()

将列表中一个指定值的所有出现替换为另一个。 更正式地,替换newVal每个元素e在list ,使(oldVal==null ? e==null : oldVal.equals(e)) 。 (此方法对列表的大小没有影响。)

参数

  • list 要 list的列表。
  • oldVal 要替换的旧值。
  • newVal 要替换 oldVal的新值。

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        replaceAll();
    }

    public static void replaceAll() {
        ArrayList<String> list = new ArrayList<>();
        list.add("5");
        list.add("10");
        list.add("1");
        list.add("133");
        list.add("231");
        list.add("2");
        // list = [5, 10, 1, 133, 231, 2]
        System.out.println("list = " + list);
        boolean b = Collections.replaceAll(list, "133", "6");
        // list = [6, 6, 6, 6, 6, 6]
        System.out.println("list = " + list);

    }
}

reverse()

  • 反转指定列表中元素的顺序。
  • 该方法运行在线性时间。
public static void reverse(List<?> list)

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        reverseDemo();
    }

    public static void reverseDemo() {
        ArrayList<String> list = new ArrayList<>();
        list.add("5");
        list.add("10");
        list.add("1");
        list.add("133");
        list.add("231");
        list.add("2");
        // list = [5, 10, 1, 133, 231, 2]
        System.out.println("list = " + list);
        Collections.reverse(list);
        // list = [2, 231, 133, 1, 10, 5]
        System.out.println("list = " + list);
    }
}

reverseOrder()

返回一个比较器,它对实现Comparable接口的对象集合施加与自然排序相反的比较。 (自然顺序是由物体本身的确定的顺序对compareTo方法)。这使得能够简单成语用于分拣(或维持)实现该对象的集合(或阵列) Comparable在反向自然顺序接口。 例如,假设a是字符串数组。

public static <T> Comparator<T> reverseOrder()

用法:

import java.util.Collections;
import java.util.TreeSet;

public class CollectionsDemo {
    public static void main(String[] args) {
        TreeSet<String> ts = new TreeSet<>(Collections.reverseOrder());
        ts.add("adcde");
        ts.add("aad");
        ts.add("kk");
        ts.add("cc");
        System.out.println("ts = " + ts);
    }
}

swap()

交换指定列表中指定位置的元素。 (如果指定的位置相等,调用此方法将保持不变。)

public static void swap(List<?> list, int i, int j)

参数:

  • list 交换元素的列表。
  • i 要交换的一个元素的索引。
  • j 要交换的其他元素的索引。

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        List<String> ts = new ArrayList<>();
        ts.add("adcde");
        ts.add("aad");
        ts.add("kk");
        ts.add("cc");
        // ts = [adcde, aad, kk, cc]
        System.out.println("ts = " + ts);
        Collections.swap(ts,2,1);
        // ts = [adcde, kk, aad, cc]
        System.out.println("ts = " + ts);
    }
}

shuffle()

使用默认的随机源随机排列指定的列表。 所有排列都以大致相等的可能性发生。

public static void shuffle(List<?> list)

用法:

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

public class CollectionsDemo {
    public static void main(String[] args) {
        List<String> ts = new ArrayList<>();
        ts.add("adcde");
        ts.add("aad");
        ts.add("kk");
        ts.add("cc");
        // ts = [adcde, aad, kk, cc]
        System.out.println("ts = " + ts);
        Collections.shuffle(ts);
        // ts = [cc, adcde, aad, kk]
        System.out.println("ts = " + ts);
    }
}

Arrays

该类包含用于操作数组的各种方法(如排序和搜索)。 该类还包含一个静态工厂,可以将数组视为列表。
如果指定的数组引用为空,则该类中的方法都抛出一个NullPointerException ,除非另有说明。

使用:

import java.util.Arrays;

public class ArraysDemo {
    public static void main(String[] args) {
        int[] nums = {1, 2, 44, 22, 4, 4, 2, 42, 23};
        Arrays.sort(nums);
        // [1, 2, 2, 4, 4, 22, 23, 42, 44]
        System.out.println(Arrays.toString(nums));
    }
}

常用方法

asList()

返回由指定数组支持的固定大小的列表。 (将返回的列表更改为“写入数组”。)该方法作为基于数组和基于集合的API之间的桥梁,与Collection.toArray()相结合 。 返回的列表是可序列化的,并实现RandomAccess 。
此方法还提供了一种方便的方式来创建一个初始化为包含几个元素的固定大小的列表:
使用该方法后不可以使用增删操作。
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
如果数组中的元素都是基本数据类型,那么会将该数组做为集合中的元素存在。

@SafeVarargs
public static <T> List<T> asList(T... a)

用法:

import java.util.Arrays;
import java.util.List;

public class ArraysDemo {
    public static void main(String[] args) {
        List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
        // [Larry, Moe, Curly]
        System.out.println(stooges);
    }
}

新增for语句

  • Collection在JDK1.5后出现的父接口Iterable就是提供了这个for语句。
  • 格式:
for(数据类型 变量名 : 数组或集合)
{
    执行语句;
}
  • 简化了对数组,集合的遍历

用法:

import java.util.ArrayList;

public class ArraysDemo {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("1");
        strings.add("2");
        strings.add("3");
        strings.add("4");
        strings.add("5");

        for (String string : strings) {
            System.out.println("string = " + string);
        }
    }
}

结果:

string = 1
string = 2
string = 3
string = 4
string = 5

for和Iterator区别

  • for只能获取集合元素,但是不能对集合进行操作。
  • Iterator除了遍历,还可以进行remove集合中的元素的动作。
  • 如果是用ListIterator,还可以在遍历过程中进行增删操作。