一、集合

1.集合的概念

Java是面向对象操作语言 ,对所有事物都是以对象的形式进行操作,为了方便对多个对象进行操作,就需要对对象进行存储 ,通常情况下,数组是较好的选择,但是一旦在数组初始化时指定了这个数组长度,这个数组长度就是不可变的,如果我们需要保存一个可以动态增长的数据,数组就不方便了 ,Java提供了集合类进行对对象的存储
Java集合类存放在java.util包中,是一个用来存放对象的容器。
集合存储有以下特点:

  1. .集合只能存放对象。比如你存入一个int型数据66放入集合中,其实它是自动转换成Integer类后存入的,Java中每一种基本数据类型都有对应的引用类型。
  2. 集合存放的都是对象的引用,而非对象本身。所以我们称集合中的对象就是集合中对象的引用。对象本身还是放在堆内存中
  3. 集合可以存放不同类型,不限数量的数据类型

集合是对Java中的数据结构的封装

2.集合的分类

Java中的集合总体分为两大类 :

  1. 单列集合
    • Collection集合 线性存储
      • List 集合 存储重复的数据 有顺序
      • Set集合 不能存储重复的集合 存储是无序的
  2. 双列集合
    • Map集合 存储数据的方式 以键值对的方式存储 key——value
  3. 学习集合的线路图
    • Collection集合容器 - 图1
    • Map集合容器 - 图2集合中 :五大接口 :Collection、List、Set、Map、Iteator八大实现类 :ArrayList、LinkedList、HashSet、TreeSet、HashMap、HashTable、TreeMap、Properties面试题 :你来说说Java中的集合容器?

      二、 Collection

      所有单列集合的最顶层的接口,里边定义了所有单列集合共性的方法
      任意的单列集合都可以使用Collection接口中的方法:
      API 方法 :
Collection 常用 API 方法说明
boolean add(E e) 在集合添加单个元素
boolean remove(Object o); 删除指定的元素
boolean contains(Object o); 查找某个元素是否存在
int size(); 获取集合中真实的元素个数
boolean isEmpty(); 判断集合是否为空
void clear(); 清空集合
boolean addAll(Collection<? extends E> c); 向集合添加多个元素
boolean containsAll(Collection<?> c); 从集合中查找多个元素是否都存在
boolean removeAll(Collection<?> c); 从集合中删除多个元素

学习Collection集合的以ArrayList的实现类操作 :
public class TestCollection {
public static void main(String[] args) {
//创建一个集合
Collection names = new ArrayList<>();
names.add(“张三丰”);
names.add(“张四丰”);
names.add(“张五丰”);
names.add(“韦一笑”);
names.add(“杨潇”);
names.add(“谢逊”);
names.add(“黛丽丝”);
names.add(“张翠山”);
names.add(“宋远桥”);
names.add(“殷天正”);

System.out.println(names.size());
//遍历 —-加强for循环
for(String name :names) {
System.out.println(name);
}

//删除
names.remove(“谢逊”);
int count = names.size();
System.out.println(count);
boolean f = names.contains(“韦一笑”);
System.out.println(f);

//names.clear();//清空集合

boolean flag = names.isEmpty();
System.out.println(flag);

//创建一个集合
Collection subNames = new ArrayList<>();
subNames.add(“汝阳王”);
subNames.add(“成昆”);
subNames.add(“空见大师”);

//把subNames集合中所有数据 添加到 names集合
names.addAll(subNames);

System.out.println(names.size()); //12
for(String s :names) {
System.out.println(s);
}

subNames.add(“王宝宝”);
//判断 names集合中 是否包含 subNames集合的中的所有数据
boolean f1 = names.containsAll(subNames);
System.out.println(f1);

// 从names集合中删除 汝阳王、成昆 、空见大师
names.removeAll(subNames);
System.out.println(“——————————“);
for(String n :names){
System.out.println(n);
}
}
}
存储自定义对象类型 (重写eqauls和toString):
public class User {
private String name;
private int age ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return “User [name=” + name + “, age=” + age + “]”;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime result + age;
result = prime
result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class TestCollectioNUser {
public static void main(String[] args) {
Collection users = new ArrayList<>();
users.add(new User(“张三丰”, 99));
users.add(new User(“宋远桥”, 88));
users.add(new User(“俞岱岩”, 87));
users.add(new User(“殷梨亭”, 86));
users.add(new User(“张翠山”, 85));

System.out.println(users.size());
System.out.println(users.isEmpty());

for(User u :users){
System.out.println(u);
}

//检查一下集合中 是否 有 张翠山
User user = new User(“张翠山”, 85);
//集合中的 contains 方法在判断 对象是否相同的时候 调用的 equals方法
//如果我们想判断自定义对象是否被包含,对象中必须重写 eqauls方法
boolean f = users.contains(user);
System.out.println(f);
System.out.println(“===============”);
Collection subUser = new ArrayList<>();
subUser.add(new User(“莫声谷”,50));
subUser.add(new User(“俞莲舟”,83));
subUser.add(new User(“张松溪”,80));

users.addAll(subUser);

for(User u :users){
System.out.println(u);
}
}
}

三 、迭代器

Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList和HashSet 等集合
(1)、Itrable接口
Iterable接口 (java.lang.Iterable) 是Java集合的顶级接口之一。Collection接口继承Iterable,所以Collection的所有子类也实现了Iterable接口 ,例如:ArrayList
(2)、Iterator 接口
迭代器(iterator)有时又称光标,当一个集合对象获取到迭代器时,光标指向这个集合的第一个元素的上方。
Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代Collection集合中的元素
所有实现了Collection接口的的集合类都有一个iterator()方法,用于返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
Iterator仅用于遍历集合,Iterator本身不存放对象

API方法 意义
boolean hasNext() 判断是否有元素
E next() 获取下一个元素
void remove() 删除当前迭代的元素

ublic class TestItrator {
public static void main(String[] args) {
Collection strs = new ArrayList<>();
strs.add(“jim”);
strs.add(“tom”);
strs.add(“lucy”);
strs.add(“lily”);
strs.add(“poly”);
strs.add(“hanmeimei”);
strs.add(“jack”);

for(String s :strs){
System.out.println(s);
}
System.out.println(“==================”);
//删除poly 集合在删除数据的时候 不能一遍遍历一遍删除 ,
//否则会报错 ConcurrentModificationException
/for(String s :strs){
if(“poly”.equals(s)){
strs.remove(“poly”);
}
System.out.println(s);
}
/
/
1.删除集合中的数据不能一边遍历 一遍删除 否则报错
2.使用集合直接 调用 remove(Object o)方法删除
3.在删除时 一定需要遍历 如何删除 ?
可以把需要删除的数据 添加到另外一个集合中 遍历完成之后调用 removeAll(Collection col)方法删除
4.利用迭代器删除
/
//删除 poly 和 lucy
Collection delCol = new ArrayList<>();
for(String s : strs){
if(“poly”.equals(s)){
delCol.add(s);
}
if(“lucy”.equals(s)){
delCol.add(s);
}
}
//调用 removeAll方法
strs.removeAll(delCol);
for(String s :strs) {
System.out.println(s);
}
System.out.println(“———————————“);
//迭代器遍历集合
Iterator iter = strs.iterator();
while(iter.hasNext()){
//如果光标下面有值 可以获取这个值
String name = iter.next();
if(“lily”.equals(name)){
//利用迭代器删除 不会报错
iter.remove();
}
System.out.println(name);
}

System.out.println(“=================”);
for(String s :strs) {
System.out.println(s);
}

System.out.println(“======================”);
Iterator iterator = strs.iterator();

while(iterator.hasNext()){
String next = iterator.next();
if(“tom”.equals(next)){
strs.remove(next); //利用 集合的方法 remove(Object o) 删除数据
}
System.out.println(next);
}

/

Collection nums = new ArrayList<>();
在集合中添加 10 个数据 使用两种方式 把集合 遍历出来
*/
}
}
面试题 :如何删除集合中的元素 ? 想问的问题 是 CoccurentMoficationException

Iterator 分析

private class Itr implements Iterator {
/*
Index of element to be returned by subsequent call to next.
*/
int cursor = 0; //迭代器的光标

  1. /**<br /> * Index of element returned by most recent call to next or<br /> * previous. Reset to -1 if this element is deleted by a call<br /> * to remove.<br /> */<br /> int lastRet = -1; // 循环时获取的当前元素的下标
  2. /**<br /> * The modCount value that the iterator believes that the backing<br /> * List should have. If this expectation is violated, the iterator<br /> * has detected concurrent modification.<br /> */<br /> int expectedModCount = modCount; //迭代器对集合进行修改的次数
  3. //判断集合中是否还有元素<br /> public boolean hasNext() {<br /> return cursor != size();<br /> }
  4. public E next() {<br /> checkForComodification();<br /> try {<br /> int i = cursor; // 0<br /> E next = get(i);<br /> lastRet = i;<br /> cursor = i + 1;<br /> return next;<br /> } catch (IndexOutOfBoundsException e) {<br /> checkForComodification();<br /> throw new NoSuchElementException();<br /> }<br /> }
  5. public void remove() {<br /> if (lastRet < 0) //必须在循环内部 才可以删除 才有元素删除<br /> throw new IllegalStateException();<br /> checkForComodification();
  6. try {<br /> AbstractList.this.remove(lastRet);<br /> if (lastRet < cursor)<br /> cursor--; //删除元素之后 ,光标要向上指一步<br /> lastRet = -1; //因为当前取出的元素被删除 <br /> expectedModCount = modCount;<br /> } catch (IndexOutOfBoundsException e) {<br /> throw new ConcurrentModificationException();<br /> }<br /> }
  7. final void checkForComodification() { // 并发判断 <br /> if (modCount != expectedModCount)<br /> throw new ConcurrentModificationException();<br /> }<br />}

四、List集合

List接口是Collection接口的子接口
它有以下特点 :

  • List集合类中的元素是有序的(添加与取出的顺序是一致的,且可以存放重复的元素)
  • List集合中的每个元素都有其对应的顺序索引,即支持索引【只有List分支有索引
  • List集合中的每个元素都可以通过索引来获取对用索引处存放元素的值 get(int index)

List集合的核心API方法 :
集合容器 - 图3
JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector:
List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法:

List 特有 API 方法说明
void add(int index, E element); 在指定索引处插入元素
E get(int index); 根据索引来获取元素
E set(int index, E element); 修改指定索引处的元素
E remove(int index); 根据索引删除元素
int indexOf(Object o); 查找元素在集合第一次出现的索引
int lastIndexOf(Object o); 查找元素在集合最后一次出现的索引
sort(Comparator<? super E> c) 集合排序
boolean addAll(int index, Collection<? extends E> c); 在指定索引处插入元素
List subList(int fromIndex, int toIndex); 截取范围[fromIndex,toIndex)内的子集合
ListIterator listIterator() 可逆序遍历的迭代器
ListIterator listIterator(int index) 从指定位置进行遍历的迭代器

/
基于List集合下标的操作
@author Administrator

/
public class TestList {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(“张三丰”);
list.add(“宋远桥”);
list.add(“张松溪”);
list.add(“俞岱岩”);
list.add(“殷梨亭”);
list.add(“张翠山”);
list.add(“莫声谷”);
list.add(“俞莲舟”);

for(int i=0;i String name = list.get(i);
System.out.print(name+” “);
}
System.out.println();
//在张翠山 的后面 把 张无忌添加进去
list.add(6, “张无忌”);
for(int i=0;i String name = list.get(i);
System.out.print(name+” “);
}
System.out.println();

//宋远桥的后面 加入 宋青书 和 周芷若
List subList = new ArrayList<>();
subList.add(“宋青书”);
subList.add(“周芷若”);

list.addAll(2, subList);
for(int i=0;i String name = list.get(i);
System.out.print(name+” “);
}
System.out.println();
//把周芷若替换成赵敏
list.set(3, “赵敏”);
for(int i=0;i String name = list.get(i);
System.out.print(name+” “);
}
System.out.println();
list.add(“宋远桥”);
list.add(“灭绝神尼”);

for(int i=0;i String name = list.get(i);
System.out.print(name+” “);
}
System.out.println();

//找出第一次出现 宋远桥的下标
int first = list.indexOf(“宋远桥”);
//找出最后一次出现 宋远桥的下标
int last = list.lastIndexOf(“宋远桥”);
System.out.println(first + “—-“+last);

//截取 下标是 1—5 的数据 [1,5)
List subList2 = list.subList(1, 5);
for(String name :subList2){
System.out.print(name + “ “);
}
}
}
/

List集合的迭代器
@author Administrator

/
public class TestListItrator {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(“张三丰”);
list.add(“宋远桥”);
list.add(“张松溪”);
list.add(“俞岱岩”);
list.add(“殷梨亭”);
list.add(“张翠山”);
list.add(“莫声谷”);
list.add(“俞莲舟”);

//正常的迭代器
Iterator iterator = list.iterator();
while(iterator.hasNext()){
String name = iterator.next();
System.out.print(name +” “);
}
System.out.println();

//可逆迭代器 迭代器 依然指向最上面
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()) {
int nextIndex = listIterator.nextIndex();
String name = listIterator.next();
System.out.print(nextIndex+”—“+name + “ “);
}
System.out.println();
//从下向上 迭代
while(listIterator.hasPrevious()){
int previousIndex = listIterator.previousIndex();
String name = listIterator.previous();
System.out.print(previousIndex + “==” + name + “ “);
}

System.out.println();
//把迭代器的光标定位任何位置 也就是说 从任意位置开始遍历
ListIterator listIterator2 = list.listIterator(4);
while(listIterator2.hasPrevious()){
int previousIndex = listIterator2.previousIndex();
String name = listIterator2.previous();
System.out.print(previousIndex + “==” + name + “ “);
}
}
}

List代码分析


以ArrayList为例 :

1.构造方法

public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;

/**<br />     * Default initial capacity.<br />     */<br />    private static final int DEFAULT_CAPACITY = 10;  //默认容量

/**<br />     * Shared empty array instance used for empty instances.<br />     */<br />    private static final Object[] EMPTY_ELEMENTDATA = {};  // 空的数组

/**<br />     * Shared empty array instance used for default sized empty instances. We<br />     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when<br />     * first element is added.<br />     */<br />    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};  //空的数组

/**<br />     * The array buffer into which the elements of the ArrayList are stored.<br />     * The capacity of the ArrayList is the length of this array buffer. Any<br />     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA<br />     * will be expanded to DEFAULT_CAPACITY when the first element is added.<br />     */<br />    transient Object[] elementData; // 声明的数组

/**<br />     * The size of the ArrayList (the number of elements it contains).<br />     *<br />     * @serial<br />     */<br />    private int size;  //计数器 记录容器的元素个数

/**<br />     * Constructs an empty list with the specified initial capacity.<br />     *<br />     * @param  initialCapacity  the initial capacity of the list<br />     * @throws IllegalArgumentException if the specified initial capacity<br />     *         is negative<br />     */<br />    //用户自己制定集合的初始化容量<br />    public ArrayList(int initialCapacity) {<br />        if (initialCapacity > 0) {<br />            this.elementData = new Object[initialCapacity];<br />        } else if (initialCapacity == 0) {<br />            this.elementData = EMPTY_ELEMENTDATA;<br />        } else {<br />            throw new IllegalArgumentException("Illegal Capacity: "+<br />                                               initialCapacity);<br />        }<br />    }

/**<br />     * Constructs an empty list with an initial capacity of ten.<br />     */<br />    //初始化一个空的集合<br />    public ArrayList() {<br />        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;<br />    }

/**<br />     * Constructs a list containing the elements of the specified<br />     * collection, in the order they are returned by the collection's<br />     * iterator.<br />     *<br />     * @param c the collection whose elements are to be placed into this list<br />     * @throws NullPointerException if the specified collection is null<br />     */<br />    //利用已经有数据的集合 创建另外一个 <br />    public ArrayList(Collection<? extends E> c) {<br />        elementData = c.toArray();<br />        if ((size = elementData.length) != 0) {<br />            // c.toArray might (incorrectly) not return Object[] (see 6260652)<br />            if (elementData.getClass() != Object[].class)<br />                elementData = Arrays.copyOf(elementData, size, Object[].class);<br />        } else {<br />            // replace with empty array.<br />            this.elementData = EMPTY_ELEMENTDATA;<br />        }<br />    }<br />    //省略N多方法<br />    <br />}ArrayList集合 底层是使用数组进行实现:
  1. 数组是有下标的,所有查询的时候很快,根据下标直接把值获取到
  2. 如果做添加或者删除的操作,需要移动元素的位置 ,所以在做添加和删除的时候,速度比较慢

    2.ArrayList如何添加数据

    /*
    Appends the specified element to the end of this list.

    @param e element to be appended to this list
    @return true (as specified by {@link Collection#add})
    /
    public boolean add(E e) {
    ensureCapacityInternal(size + 1); // 检测是否超过容量
    elementData[size++] = e;
    return true;
    }检测容量:private void ensureCapacityInternal(int minCapacity) {
    //检测是否是空数组
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    //如果是空数组 设置一个容量 DEFAULT_CAPACITY = 10
    minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 检测容量
    ensureExplicitCapacity(minCapacity);
    }

private void ensureExplicitCapacity(int minCapacity) {
modCount++; //数组中数据化更新 将来和删除有关 和线程也有关 为了防止多线程操作导致的数据的不一致

// 检测容量是否超标<br />    if (minCapacity - elementData.length > 0)<br />        grow(minCapacity); // 扩容<br />}

private void grow(int minCapacity) { // minCapacity size + 1
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 每次扩容1.5倍
if (newCapacity - minCapacity < 0) // 扩容之后 是否比容器的容量+1 要小
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) // 扩容之后的容量是否超过 Integer.MAX_VALUE - 8
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //扩容之后的拷贝数据
}

3.删除方法 (在循环删除时 会报错)

public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
//循环判断 需要删除的元素的下标
if (o.equals(elementData[index])) {
fastRemove(index); //删除操作
return true;
}
}
return false;
}

private void fastRemove(int index) {
modCount++; //记录更新次数
int numMoved = size - index - 1; //计算需要移动的元素个数
if (numMoved > 0) //如果删除的不是最后一个元素 开始移动元素的位置
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//删除的是最后一个位置 直接把最后一个位置置成 null 然后size-1
elementData[—size] = null; // clear to let GC do its work
}

4.删除时候的异常

Exception in thread “main” java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.woniu.k15.test.TestArrayList.main(TestArrayList.java:21)在循环操作的时候,每次都会走下面的代码 :/
expectedModCount : 集合的容量
modCount : 集合更新次数
*/
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}为什么在循环删除的时候 会报上述错误 ,因为在删除的时候 ,modCount 更新次数会增加 ,但是expectedModCount 没有更新,下一次循环的时候 ,检测 更新次数和 容量容量 expectedModCount 的时候 ,就不一样 执行checkForComodification 就抛出异常为什么迭代器删除的时候 没有报出此异常 因为 在迭代器删除时 更新了 expectedModCount 的值 =- modCountpublic void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {<br />        ArrayList.this.remove(lastRet);<br />        cursor = lastRet;<br />        lastRet = -1;<br />        expectedModCount = modCount;  //更新了 !!!!!!!!<br />    } catch (IndexOutOfBoundsException ex) {<br />        throw new ConcurrentModificationException();<br />    }<br />}

五、比较器

在开发过程中,我们经常会涉及到对象比较的问题,对于JDK1.8而言,有3种实现对象比较的方法:
1、覆写Object类的equals()方法;
2、继承Comparable接口,并实现compareTo()方法;
3、定义一个单独的对象比较器,继承自Comparator接口,实现compare()方法。

1.Comparable

提供给类实现,定义此类的对象如何进行比较 ,也就是说定义对象比较的标准 。
public class User implements Comparable {
private String name ;
private int age ;
private double weight;

//省略 set、get 构造方法 equals方法 toString

/*
按照年龄进行比较 如果年龄相同 就比较体重
整数 :前面的对象 大于后面的对象
负数 : 前面的对象小于后面的对象
0 :两个对象相同
/
@Override
public int compareTo(User o) {
if(this.age > o.age) {
return 1;
}else if(this.age < o.age){
return -1;
}else {
if(this.weight - o.weight > 0){
return 1;
}else if(this.weight - o.weight < 0){
return -1;
}
}
return 0;
}
}
测试 :
public class TestUser {
public static void main(String[] args) {
/
User u1 = new User(“jack”, 18, 70);
User u2 = new User(“tom”,18,80);
//调用比较的方法
int i = u1.compareTo(u2);
if(i >0) {
System.out.println(u1 +”大于” + u2);
}else if(i < 0){
System.out.println(u1 +”小于” + u2);
}else {
System.out.println(u1 +”==” + u2);
}
/

Date d1 = new Date(35365767657L);
Date d2 = new Date(57676423432L);

int compareTo = d1.compareTo(d2);
System.out.println(compareTo); //负数

String s1 = new String(“ddd”);
String s2 = new String(“ccc”);
int compareTo2 = s1.compareTo(s2);
System.out.println(compareTo2); // 整数

Integer n1 = new Integer(100);
Integer n2 = new Integer(200);
int compareTo3 = n1.compareTo(n2);// 负数

/
JDK提供的API类中 有很多已经实现了Comparable接口 这样就可以直接比较
比较的标准由 JDK 已经定义好的
/
}
}
定义一个商品类 :Goods ,属性 :gname ,price ,生产日期(createDate) 定义商品对象的比较标准
先比较价格 、价格相同 ,在比较生产日期 ,生产日期晚的产品 大

2.Comparator

Comparator 也是一个接口 ,也是一个比较器 ,这个接口通常在集合中使用,可以对集合中的对象进行排序
定义对象的排序规则:
public class MyuComparator implements Comparator{

@Override<br />    public int compare(User o1, User o2) {<br />        if(o1.getAge() > o2.getAge()) {<br />            return 1;<br />        }else if(o1.getAge() < o2.getAge()){<br />            return -1;<br />        }else {<br />            if(o1.getWeight() - o2.getWeight() > 0){<br />                return 1;<br />            }else if(o1.getWeight() - o2.getWeight() < 0){<br />                return -1;<br />            }<br />        }<br />        return 0;<br />    }<br />}<br />针对用户进行排序:<br />public static void main(String[] args){<br />    List<User> users = new ArrayList<>();<br />    users.add(new User("jim", 18, 48));<br />    users.add(new User("tom", 23, 58));<br />    users.add(new User("lucy", 21, 45));<br />    users.add(new User("jack", 18, 67));<br />    users.add(new User("poly", 3, 10));

for(User u :users) {<br />        System.out.println(u);<br />    }<br />    System.out.println("============");<br />    //排序  <br />    /*<br />         * java.lang.ClassCastException: <br />         * com.woniu.day16.compa.User cannot be cast to java.lang.Comparable<br />         * 当我们调用 Sort方法时 ,他会把用户对象 转成 Comparable类型  调用 comparateTo方法,<br />         * 对对象进行比较 <br />         */<br />    users.sort(new MyuComparator());<br />    for(User u :users) {<br />        System.out.println(u);<br />    }<br />}<br />还可以使用匿名内部类 进行排序 :<br />public static void main(String[] args){<br />    List<User> users = new ArrayList<>();<br />    users.add(new User("jim", 18, 48));<br />    users.add(new User("tom", 23, 58));<br />    users.add(new User("lucy", 21, 45));<br />    users.add(new User("jack", 18, 67));<br />    users.add(new User("poly", 3, 10));

for(User u :users) {<br />        System.out.println(u);<br />    }<br />    System.out.println("============");<br />    //排序  <br />    users.sort(new Comparator<User>() {<br />        @Override<br />        public int compare(User o1, User o2) {<br />            if(o1.getAge() > o2.getAge()) {<br />                return 1;<br />            }else if(o1.getAge() < o2.getAge()){<br />                return -1;<br />            }else {<br />                if(o1.getWeight() - o2.getWeight() > 0){<br />                    return 1;<br />                }else if(o1.getWeight() - o2.getWeight() < 0){<br />                    return -1;<br />                }<br />            }<br />            return 0;<br />        }<br />    });<br />    for(User u :users) {<br />        System.out.println(u);<br />    }<br />}

四、LinkedList

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作
双链表实现了List和Deque接口
栈 :是一种数据结构,先进后出
队列:是一种数据结构,先进先出
LinkedList 它的底层不再是数组结构,它的底层是双向链表结构。它将列表中的每个对象都有一个单独的存储空间,而且每个存储空间都具备上一个节点,和下一个节点的索引!
集合容器 - 图4

1.构造方法

public LinkedList()
public LinkedList(Collection<? extends E> c)

2.API 方法案例一 :添加的方法

public class TestLinkedList {

public static void main(String[] args) {<br />       // List<String> names = new LinkedList(); //不推荐<br />        LinkedList<String> pets = new LinkedList(); //推荐<br />        pets.add("pig");<br />        pets.add("cat");<br />        pets.add("dog");//添加对象<br />        for(String p :pets){<br />            System.out.println(p);<br />        }<br />        pets.add(1, "snake"); //指定下标添加<br />        System.out.println("======");<br />        for(String p :pets){<br />            System.out.println(p);<br />        }<br />        System.out.println("====");<br />        List<String> str = new ArrayList<>();<br />        str.add("tiger");<br />        str.add("leo");

   // pets.addAll(str); //把一个集合中元素添加进去<br />        pets.addAll(2, str);<br />        for(String p :pets){<br />            System.out.println(p);<br />        }

    pets.addFirst("张三丰"); //添加到头<br />        pets.addLast("张无忌"); //添加到尾<br />        System.out.println("=======");<br />        for(String p :pets){<br />            System.out.println(p);<br />        }<br />        //以上是添加方法<br />        System.out.println("=======================");<br />        String p1 = pets.get(3);  //根据下标获取<br />        String first = pets.getFirst(); //获取头元素<br />        String last = pets.getLast(); //获取尾元素

    System.out.println(p1 +"==="+first+"===="+last);<br />       // pets.p<br />    }<br />}

3.案例二 :删除方法

public class TestLinkedList {

public static void main(String[] args) {<br />       // List<String> names = new LinkedList(); //不推荐<br />        LinkedList<String> pets = new LinkedList(); //推荐<br />        pets.add("pig");<br />        pets.add("cat");<br />        pets.add("dog");<br />        pets.add("snake");<br />        pets.add("tiger");<br />        pets.add("leo");<br />        System.out.println("删除之前:");<br />        for(String s :pets){<br />            System.out.println(s);<br />        }

    //删除方法<br />        //pets.remove(); //删除最上面的元素<br />       // pets.remove(2); //根据下标删除<br />        //pets.remove("leo"); //根据元素对象删除  对象一定要重写equals方法<br />        pets.removeFirst();<br />        pets.removeLast();<br />        System.out.println("删除之后:");<br />        for (String  s :pets){<br />            System.out.println(s);<br />        }<br />    }<br />}

4.案例三:遍历方法(三种):

public class TestLinkedList01 {

public static void main(String[] args) {<br />       // List<String> names = new LinkedList(); //不推荐<br />        LinkedList<String> pets = new LinkedList(); //推荐<br />        pets.add("pig");<br />        pets.add("cat");<br />        pets.add("dog");<br />        pets.add("snake");<br />        pets.add("tiger");<br />        pets.add("leo");<br />        System.out.println("加强for循环:");<br />        for(String s :pets){<br />            System.out.println(s);<br />        }<br />        System.out.println("普通for循环:");<br />        for(int i=0;i<pets.size();i++){<br />            System.out.println(pets.get(i));<br />        }<br />        System.out.println("迭代器循环1 :");<br />        Iterator<String> iterator = pets.iterator();<br />        while (iterator.hasNext()){<br />            System.out.println(iterator.next());<br />        }

    System.out.println("迭代器循环2 :");<br />        ListIterator<String> iter = pets.listIterator();<br />        while (iter.hasNext()){<br />            System.out.println(iter.next());<br />        }<br />        System.out.println("=====");<br />        while (iter.hasPrevious()){<br />            System.out.println(iter.previous());<br />        }<br />    }<br />}

5.案例四:Deque接口中的方法:

public class TestLinkedList02 {

public static void main(String[] args) {<br />       // List<String> names = new LinkedList(); //不推荐<br />        LinkedList<String> pets = new LinkedList(); //推荐<br />        pets.add("pig");<br />        pets.add("cat");<br />        pets.add("dog");<br />        pets.add("snake");<br />        pets.add("tiger");<br />        pets.add("leo");

    String element = pets.element();//返回头元素 但是不删除<br />        String peek = pets.peek();//返回头元素不删除<br />        String s = pets.peekFirst();//返回头元素 不删除<br />        String s1 = pets.peekLast();//反击尾元素 不删除<br />        System.out.println(element+"---"+peek+"---"+s+"----"+s1);

    for (String ss : pets) {<br />            System.out.println(ss);<br />        }<br />        System.out.println("======================");<br />        pets.offer("bird"); //添加到尾部<br />        pets.offerFirst("rabbit"); //添加到 头部<br />        for (String str :pets){<br />            System.out.println(str);<br />        }

    System.out.println("==============");<br />        String poll = pets.poll(); //取出头元素 并删除<br />        System.out.println("-----"+poll);<br />        for (String str :pets){<br />            System.out.println(str);<br />        }<br />    }<br />}

6.案例五 :排序

public class TestLinkedList02 {

public static void main(String[] args) {<br />       // List<String> names = new LinkedList(); //不推荐<br />        LinkedList<String> pets = new LinkedList(); //推荐<br />        pets.add("pig");<br />        pets.add("cat");<br />        pets.add("dog");<br />        pets.add("snake");<br />        pets.add("tiger");<br />        pets.add("leo");

    //升序<br />        pets.sort(new Comparator<String>() {<br />            @Override<br />            public int compare(String o1, String o2) {<br />                return o1.compareTo(o2);<br />            }<br />        });

    for (String s :pets){<br />            System.out.println(s);<br />        }<br />        System.out.println("=====");<br />        System.out.println("降序:");<br />        pets.sort(new Comparator<String>() {<br />            @Override<br />            public int compare(String o1, String o2) {<br />                //return o1.compareTo(o2)* -1;<br />                return o2.compareTo(o1);<br />               /* int len1 = o1.length();<br />                int len2 = o2.length();<br />                int lim = Math.min(len1, len2);<br />                char v1[] = o1.toCharArray();<br />                char v2[] = o2.toCharArray();

            int k = 0;<br />                while (k < lim) {<br />                    char c1 = v1[k];<br />                    char c2 = v2[k];<br />                    if (c1 != c2) {<br />                        return c2 - c1;<br />                    }<br />                    k++;<br />                }<br />                return len2 - len1;*/<br />            }<br />        });

    for (String s :pets){<br />            System.out.println(s);<br />        }<br />    }<br />}

五、Vector (线程安全的集合)

是一个线程安全的集合 ,功能和ArrayList完全一样 ,因为都是实现的List接口 ,都是使用数组实现的,唯一不同的是,他的每一个方法都加了锁:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
这个集合除了在方法上加锁之外 ,保证线程安全,其他的和ArrayList都完全一样 ,但是心在如果我们使用线程安全的集合也不会使用Vecttor ,所以这个集合后面会被淘汰掉