一、集合
1.集合的概念
Java是面向对象操作语言 ,对所有事物都是以对象的形式进行操作,为了方便对多个对象进行操作,就需要对对象进行存储 ,通常情况下,数组是较好的选择,但是一旦在数组初始化时指定了这个数组长度,这个数组长度就是不可变的,如果我们需要保存一个可以动态增长的数据,数组就不方便了 ,Java提供了集合类进行对对象的存储。
Java集合类存放在java.util包中,是一个用来存放对象的容器。
集合存储有以下特点:
- .集合只能存放对象。比如你存入一个int型数据66放入集合中,其实它是自动转换成Integer类后存入的,Java中每一种基本数据类型都有对应的引用类型。
- 集合存放的都是对象的引用,而非对象本身。所以我们称集合中的对象就是集合中对象的引用。对象本身还是放在堆内存中
- 集合可以存放不同类型,不限数量的数据类型
2.集合的分类
Java中的集合总体分为两大类 :
- 单列集合
- Collection集合 线性存储
- List 集合 存储重复的数据 有顺序
- Set集合 不能存储重复的集合 存储是无序的
- Collection集合 线性存储
- 双列集合
- Map集合 存储数据的方式 以键值对的方式存储 key——value
- 学习集合的线路图
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.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.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.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.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.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
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
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
while(iterator.hasNext()){
String next = iterator.next();
if(“tom”.equals(next)){
strs.remove(next); //利用 集合的方法 remove(Object o) 删除数据
}
System.out.println(next);
}
/
Collection
*/
}
}
面试题 :如何删除集合中的元素 ? 想问的问题 是 CoccurentMoficationException
Iterator 分析
private class Itr implements Iterator
/*
Index of element to be returned by subsequent call to next.
*/
int cursor = 0; //迭代器的光标
/**<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; // 循环时获取的当前元素的下标
/**<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; //迭代器对集合进行修改的次数
//判断集合中是否还有元素<br /> public boolean hasNext() {<br /> return cursor != size();<br /> }
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 /> }
public void remove() {<br /> if (lastRet < 0) //必须在循环内部 才可以删除 才有元素删除<br /> throw new IllegalStateException();<br /> checkForComodification();
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 /> }
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方法 :
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 |
截取范围[fromIndex,toIndex)内的子集合 |
ListIterator |
可逆序遍历的迭代器 |
ListIterator |
从指定位置进行遍历的迭代器 |
/
基于List集合下标的操作
@author Administrator
/
public class TestList {
public static void main(String[] args) {
List
list.add(“张三丰”);
list.add(“宋远桥”);
list.add(“张松溪”);
list.add(“俞岱岩”);
list.add(“殷梨亭”);
list.add(“张翠山”);
list.add(“莫声谷”);
list.add(“俞莲舟”);
for(int i=0;i
System.out.print(name+” “);
}
System.out.println();
//在张翠山 的后面 把 张无忌添加进去
list.add(6, “张无忌”);
for(int i=0;i
System.out.print(name+” “);
}
System.out.println();
//宋远桥的后面 加入 宋青书 和 周芷若
List
subList.add(“宋青书”);
subList.add(“周芷若”);
list.addAll(2, subList);
for(int i=0;i
System.out.print(name+” “);
}
System.out.println();
//把周芷若替换成赵敏
list.set(3, “赵敏”);
for(int i=0;i
System.out.print(name+” “);
}
System.out.println();
list.add(“宋远桥”);
list.add(“灭绝神尼”);
for(int i=0;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
for(String name :subList2){
System.out.print(name + “ “);
}
}
}
/
List集合的迭代器
@author Administrator
/
public class TestListItrator {
public static void main(String[] args) {
List
list.add(“张三丰”);
list.add(“宋远桥”);
list.add(“张松溪”);
list.add(“俞岱岩”);
list.add(“殷梨亭”);
list.add(“张翠山”);
list.add(“莫声谷”);
list.add(“俞莲舟”);
//正常的迭代器
Iterator
while(iterator.hasNext()){
String name = iterator.next();
System.out.print(name +” “);
}
System.out.println();
//可逆迭代器 迭代器 依然指向最上面
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
while(listIterator2.hasPrevious()){
int previousIndex = listIterator2.previousIndex();
String name = listIterator2.previous();
System.out.print(previousIndex + “==” + name + “ “);
}
}
}
List代码分析
1.构造方法
public class ArrayList
implements List
{
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集合 底层是使用数组进行实现:
- 数组是有下标的,所有查询的时候很快,根据下标直接把值获取到
- 如果做添加或者删除的操作,需要移动元素的位置 ,所以在做添加和删除的时候,速度比较慢
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 它的底层不再是数组结构,它的底层是双向链表结构。它将列表中的每个对象都有一个单独的存储空间,而且每个存储空间都具备上一个节点,和下一个节点的索引!
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 ,所以这个集合后面会被淘汰掉