【原】Java学习笔记026 - 集合

时间:2024-01-11 17:09:02
 package cn.temptation;

 public class Sample01 {
public static void main(String[] args) {
// 需求:从三国演义中评选出四个最帅的武将,并存储下来 // 因为具备了面向对象的思想,所以创建四个对象来存储
Hero hero1 = new Hero("张飞", 18);
Hero hero2 = new Hero("赵云", 16);
Hero hero3 = new Hero("陆逊", 17);
Hero hero4 = new Hero("张辽", 20); // 因为这四个对象有着相同的语义,所以考虑把它们放在一个数组中,对象的数组简称对象数组
Hero[] heros = new Hero[4];
System.out.println(heros); // [Lcn.temptation.Hero;@15db9742 heros[0] = hero1;
heros[1] = hero2;
heros[2] = hero3;
heros[3] = hero4; // 一般for循环的遍历
for (int i = 0; i < heros.length; i++) {
Hero item = heros[i];
System.out.println(item);
} // 增强型for循环的遍历
for (Hero item : heros) {
System.out.println(item);
}
}
} // 英雄类
class Hero {
// 成员变量
private String name;
private int age; // 构造函数
public Hero() {
super();
} public Hero(String name, int age) {
super();
this.name = name;
this.age = 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;
} @Override
public String toString() {
return "武将 [姓名:" + name + ", 年龄:" + age + "]";
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection; public class Sample02 {
public static void main(String[] args) {
/*
* 问题:
* 选出四大帅哥武将后,张飞被杀,然后大家重新选,有两个人票数相同,变成五大帅哥武将
* 这时,数据存储的数组出现问题了,之前设置的长度为4,现在要放入5个元素,不得不修改数组的长度
* 像这样的数组长度的变化对于使用起来很不方便
*
* 针对这类问题,Java提供了适应变化的解决方案-----集合
*
* 数组 和 集合 的区别:
* 1、长度上的区别:数组长度固定,集合长度不固定(可变的)
* 2、元素上的区别:数组的元素都是同一类型,集合的元素可以是不同类型的
* 3、元素的数据类型上的区别:数组的元素的数据类型可以是基本数据类型、也可以是引用数据类型;集合的元素的数据类型只能是引用数据类型
*
* 集合相关的接口 和 类 都位于 java.util 中
*
* 集合中的接口 和 实现类很多,如何掌握?从上向下进行学习? 还是从下向上进行学习?
* 这里选择从上向下进行学习,从根接口开始,每一级子接口只要学习一下父接口中没有的特性方法就可以了
*
* 集合可以分为 单列集合(根接口:Collection接口) 和 双列集合(根接口:Map接口)
*
* Collection接口:Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。
* 一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
* JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。
* 此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
*
* Collection接口的常用成员方法:
* 1、容量
* int size() :返回此 collection 中的元素数。
*
* 2、添加功能
* boolean add(E e) :确保此 collection 包含指定的元素(可选操作)。
*
* 3、删除功能
* void clear() :移除此 collection 中的所有元素(可选操作)。
* boolean remove(Object o) :从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
*
* 4、判断功能
* boolean contains(Object o) :如果此 collection 包含指定的元素,则返回 true。
* boolean isEmpty() :如果此 collection 不包含元素,则返回 true。
*
*/ // 创建Collection接口类型的对象,因为Collection接口没有任何直接实现类,所以在其子接口List 和 Set上找实现类,找到实现List接口的ArrayList类
Collection collection = new ArrayList();
System.out.println("collection:" + collection); // collection:[] // 添加功能
collection.add("China");
collection.add("USA");
collection.add("Japan"); System.out.println("add:" + collection.add("England")); // add:true System.out.println("size:" + collection.size()); // 查看源码,会列出全部实现了Collection接口的add方法的各种子接口或实现类,选择ArrayList
// public boolean add(E e) {
// ensureCapacityInternal(size + 1); // Increments modCount!!
// elementData[size++] = e;
// return true;
// } System.out.println("-------------------------------------------------------"); // 删除功能
// collection.clear(); System.out.println("remove:" + collection.remove("Japan")); // true
System.out.println("remove:" + collection.remove("France")); // false System.out.println("size:" + collection.size()); System.out.println("-------------------------------------------------------"); // 判断功能
System.out.println("contains:" + collection.contains("China")); // true
System.out.println("contains:" + collection.contains("France")); // false System.out.println("isEmpty:" + collection.isEmpty()); // false System.out.println("collection:" + collection); System.out.println("-------------------------------------------------------"); // 【比较数组、字符串、字符串缓冲区、集合用来描述容量或长度的方法或属性】
// 1、数组:长度 length属性,注意不是length()方法
// 2、字符串:长度 length()方法
// 3、字符串缓冲区:容量 capacity() ----- 设定值;长度length(),实际值
// 4、集合:长度(元素数量)size() int[] arr = new int[3];
System.out.println(arr.length); // String str = "123";
System.out.println(str.length()); // StringBuffer sb = new StringBuffer(str);
System.out.println(sb.capacity()); //
System.out.println(sb.length()); //
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection; public class Sample03 {
public static void main(String[] args) {
/*
* Collection接口的常用成员方法:
* 1、添加功能
* boolean addAll(Collection<? extends E> c) :将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
*
* 2、删除功能
* boolean removeAll(Collection<?> c) :移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
*
* 3、判断功能
* boolean containsAll(Collection<?> c) :如果此 collection 包含指定 collection 中的所有元素,则返回 true。
*
* 4、交集功能
* boolean retainAll(Collection<?> c) :仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
*/ Collection collection1 = new ArrayList();
collection1.add("中国");
collection1.add("美国");
System.out.println("collection1:" + collection1); // collection1:[中国, 美国] Collection collection2 = new ArrayList();
collection2.add("中国");
collection2.add("德国");
System.out.println("collection2:" + collection2); // collection2:[中国, 德国] // 添加功能:把作为形参的集合的全部元素都加入到原集合中,不论是否重复
collection1.addAll(collection2);
System.out.println("collection1:" + collection1); // collection1:[中国, 美国, 中国, 德国]
System.out.println("collection2:" + collection2); // collection2:[中国, 德国] // addAll()方法返回:如果此 collection 由于调用而发生更改,则返回 true
//(原集合中只要添加了至少一个元素,就返回true,如果原集合中一个元素都没有改变,就返回false)
Collection collection3 = new ArrayList();
System.out.println("collection1:" + collection1.addAll(collection3)); // collection1:false System.out.println("-------------------------------------------------"); Collection collection4 = new ArrayList();
collection4.add("中国");
collection4.add("美国"); // 删除功能:把作为形参的集合的全部元素和原集合中的元素进行比较,剔除相同的元素
collection1.removeAll(collection4);
System.out.println("collection1:" + collection1); // collection1:[德国]
System.out.println("collection4:" + collection4); // collection4:[中国, 美国] // removeAll()方法返回:如果此 collection 由于调用而发生更改,则返回 true
Collection collection5 = new ArrayList();
System.out.println("collection1:" + collection1.removeAll(collection5)); // collection1:false System.out.println("-------------------------------------------------"); Collection collection6 = new ArrayList();
collection6.add("德国"); // 判断功能:如果此集合包含指定集合中的所有元素,则返回true(子集关系)
System.out.println("containsAll:" + collection1.containsAll(collection6)); // containsAll:true collection6.add("俄罗斯");
System.out.println("containsAll:" + collection1.containsAll(collection6)); // containsAll:false System.out.println("-------------------------------------------------"); Collection collection7 = new ArrayList();
collection7.add("中国");
collection7.add("日本"); collection1.add("中国"); System.out.println("collection1:" + collection1); // collection1:[德国, 中国]
System.out.println("collection7:" + collection7); // collection7:[中国, 日本] System.out.println("retainAll:" + collection1.retainAll(collection7)); // retainAll:true System.out.println("collection1:" + collection1); // collection1:[中国]
System.out.println("collection7:" + collection7); // collection7:[中国, 日本] Collection collection8 = new ArrayList();
collection8.add("中国"); System.out.println("collection1:" + collection1); // collection1:[中国]
System.out.println("collection8:" + collection8); // collection8:[中国] System.out.println("retainAll:" + collection1.retainAll(collection8)); // retainAll:false // 交集功能:如果原集合因为和指定集合获取相同的元素而让自身的元素个数发生改变,则返回true,否则返回false
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection; public class Sample04 {
public static void main(String[] args) {
/*
* Collection接口的常用成员方法:
* 1、Object[] toArray() :返回包含此 collection 中所有元素的数组。
*/
Collection collection = new ArrayList(); collection.add("中国");
collection.add("美国");
collection.add("德国"); Object[] arr = collection.toArray(); for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
} for (Object item : arr) {
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection; public class Sample05 {
public static void main(String[] args) {
/*
* Collection接口的常用成员方法:
* 1、Object[] toArray() :返回包含此 collection 中所有元素的数组。
*/
Collection collection = new ArrayList(); Student student1 = new Student("吕布", 20);
Student student2 = new Student("貂蝉", 16); collection.add(student1);
collection.add(student2); System.out.println(collection); // [学生 [姓名为:吕布, 年龄为:20], 学生 [姓名为:貂蝉, 年龄为:16]] Object[] arr = collection.toArray(); // 增强型for循环
for (Object item : arr) {
// 下面两句效果相同,因为item实际就是Student类类型的对象
// System.out.println(item);
System.out.println((Student)item);
} // 一般for循环
for (int i = 0; i < arr.length; i++) {
// 写法1
// System.out.println(arr[i]);
// 写法2:定义Student类型的变量,使用向下转型
Student temp = (Student) arr[i];
System.out.println(temp);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; public class Sample06 {
public static void main(String[] args) {
/*
* Collection接口的常用成员方法:
* 1、Iterator<E> iterator() :返回在此 collection 的元素上进行迭代的迭代器。
*
* 迭代器 Iterator 接口:对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。
*
* 迭代:重复反馈的活动,其目的通常是为了逼近所需目标或结果。每次对过程的重复称为一次"迭代"。而每次迭代得到的结果会作为下一次迭代的初始值。
*
* Iterator接口的常用成员方法:
* 1、boolean hasNext() :如果仍有元素可以迭代,则返回 true。
* 2、Object next() :返回迭代的下一个元素。
*
*/ Collection collection = new ArrayList();
collection.add("China");
collection.add("USA");
collection.add("Japan"); for (Object item : collection) {
System.out.println(item);
} System.out.println("-------------------------------------------"); Iterator iterator = collection.iterator(); // Object obj1 = iterator.next();
// System.out.println(obj1); // China
//
// Object obj2 = iterator.next();
// System.out.println(obj2); // USA
//
// Object obj3 = iterator.next();
// System.out.println(obj3); // Japan // 执行异常:java.util.NoSuchElementException
// Object obj4 = iterator.next();
// System.out.println(obj4); // 因为使用Iterator对象的next()方法,操作获取下一个元素时可能会发生异常,所以需要先判断一下下一个元素是否可以迭代获取
// if (iterator.hasNext()) {
// System.out.println(iterator.next());
// }
//
// if (iterator.hasNext()) {
// System.out.println(iterator.next());
// }
//
// if (iterator.hasNext()) {
// System.out.println(iterator.next());
// }
//
// if (iterator.hasNext()) {
// // 因为collection对象中只有三个元素,所以这里的iterator.hasNext()返回false,也就不会再操作next方法
// System.out.println(iterator.next());
// } // 上面写法比较傻,进行改进:重复的操作可以考虑使用循环
while (iterator.hasNext()) {
System.out.println(iterator.next());
} // 联想一下Scanner类,也有hasNext方法和next方法,查看一下,发现Scanner类实现了Iterator接口
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; public class Sample07 {
public static void main(String[] args) {
Collection collection = new ArrayList(); collection.add(new Student("张三", 18));
collection.add(new Student("李四", 20));
collection.add(new Student("王五", 16));
collection.add(new Student("赵六", 22)); Iterator iterator = collection.iterator(); // 写法1、使用while循环进行迭代
// while (iterator.hasNext()) {
// // 写法1-1
// System.out.println(iterator.next());
//
// // 写法1-2
//// Student student = (Student) iterator.next();
//// System.out.println(student);
// } System.out.println("-------------------------------------"); // 写法2、使用一般for循环进行迭代,考虑到while循环和for循环其实是一样的
// for (; iterator.hasNext(); ) {
// System.out.println(iterator.next());
// } System.out.println("-------------------------------------"); // 写法3、使用eclipse提供的for循环迭代Collection的模板
// for (Iterator iteratorEx = collection.iterator(); iteratorEx.hasNext();) {
// System.out.println(iteratorEx.next());
// } // 错误的写法
// 对于集合是奇数元素,这样的写法产生执行异常:java.util.NoSuchElementException
// 对于集合是偶数元素,会显示实际元素数量的一半,且数据不正确
// 原因:
// iterator.next()这个方法不调用不执行,调用了自然要获取下一个元素,48行语句中有两次对iterator.next()方法的调用
while (iterator.hasNext()) {
System.out.println("姓名为:" + ((Student)(iterator.next())).getName() + ",年龄为:" + ((Student)(iterator.next())).getAge());
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator; public class Sample08 {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add("China");
collection.add("USA");
collection.add("Japan"); Iterator iterator = collection.iterator(); // 为什么迭代器要设计成这样?
// 1、为什么设计为接口?因为接口描述的是后天具备的能力,灵活性很好,只要实现了接口定义的方法就具备了接口的能力
// 2、为什么接口最终的实现是在各个集合的具体实现类中创建类的内部类对象?
// 集合中接口很多,最终实现类也很多,各种实现类的结构会有所不同,不定义具体的实现,只通过接口定义实现的方法声明,给予各个实现类独立实现
// 在各个实现类的内部通过内部类的形式,可以让内部类很方便的访问到其所在的外部类的成员
}
} // 查看迭代器Iterator接口的源码
//public interface Iterator<E> {
// boolean hasNext();
// E next();
//} // 查看可迭代接口 Iterable接口的源码
//public interface Iterable {
// Iterator<T> iterator();
//} // 查看ArrayList类的源码
//public Iterator<E> iterator() {
// return new Itr();
//} // 查看内部类Itr类的源码
//private class Itr implements Iterator<E> {
// int cursor; // index of next element to return 游标 指针
// int lastRet = -1; // index of last element returned; -1 if no such
// int expectedModCount = modCount;
//
// public boolean hasNext() {
// return cursor != size;
// }
//
// @SuppressWarnings("unchecked")
// public E next() {
// checkForComodification();
// int i = cursor;
// if (i >= size)
// throw new NoSuchElementException();
// Object[] elementData = ArrayList.this.elementData;
// if (i >= elementData.length)
// throw new ConcurrentModificationException();
// cursor = i + 1;
// return (E) elementData[lastRet = i];
// }
//}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class Sample09 {
public static void main(String[] args) {
/*
* List接口:继承自Collection接口 和 Iterable接口(多继承)
* 有序的 collection(也称为序列)。
* 此接口的用户可以对列表中每个元素的插入位置进行精确地控制。
* 用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
*
* 与 set接口不同,列表通常允许重复的元素。
*/
List list = new ArrayList(); list.add("中国");
list.add("美国"); System.out.println("list:" + list); // list:[中国, 美国] Iterator iterator = list.iterator(); while (iterator.hasNext()) {
// 写法1
// System.out.println(iterator.next()); // 写法2
String str = (String) iterator.next();
System.out.println(str);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class Sample10 {
public static void main(String[] args) {
/*
* List接口的特点:
* 1、有序性:元素放入List集合中的顺序 和 遍历List集合时看到的顺序是一致
* 2、可重复性:元素的内容可以相同
*/ List list = new ArrayList(); list.add("艾欧尼亚");
list.add("黑色玫瑰");
list.add("皮城警备");
list.add("黑色玫瑰"); Iterator iterator = list.iterator(); while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class Sample11 {
public static void main(String[] args) {
List list = new ArrayList(); list.add(new Student("张三", 16));
list.add(new Student("李四", 18));
list.add(new Student("王五", 20));
list.add(new Student("李四", 18)); Iterator iterator = list.iterator(); while (iterator.hasNext()) {
Student temp = (Student) iterator.next();
System.out.println(temp);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator; public class Sample12 {
public static void main(String[] args) {
/*
* List接口的常用三个实现类:
* 1、ArrayList类:
* List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。
* 除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
* 底层实现通过数组这个数据结构
*
* 2、Vector类:
* Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。
* 但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。
* 底层实现通过数组这个数据结构
*
* 3、LinkedList类:
* List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。
* 除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。
* 这些操作允许将链接列表用作堆栈、队列或双端队列。
* 底层实现通过链表这个数据结构
*
* 数据结构:
* 1、数组:存储同一种类型的多个元素的容器
* int[] arr = { 99, 98, 97 };
* 存储形式: 99 98 97
* 索引: 0 1 2
* 使用场景1、获取元素内容为98的元素,通过索引直接找到元素arr[1]
* 使用场景2、在元素内容为98的元素后添加一个元素内容为96,操作步骤如下:
* A:定义一个新数组,长度为 3 + 1 = 4
* B:在原数组中找到内容为98的元素及其之前的所有元素,全部复制到新数组中存储下来
* C:在新数组中添加内容为96的元素
* D:在原数组中找到内容为98的元素之后的所有元素,复制到新数组中存储下来(索引都要加1)
* 存储形式: 99 98 96 97
* 索引: 0 1 2 3
* 使用场景3、在初始数组中删除元素内容为98,操作步骤如下:
* A:定义一个新数组,长度为 3 - 1 = 2
* B:在原数组中找到内容为98的元素之前的所有元素,全部复制到新数组中存储下来
* C:找到内容为98的元素,不复制到新数组中
* D:在原数组中找到内容为98的元素之后的所有元素,复制到新数组中存储下来(索引都要减1)
* 存储形式: 99 97
* 索引: 0 1
*
* 数组结构的特点:查找快速高效、增删复杂低效
*
* 2、链表(单向链表):由一个链式结构把多个节点组合(包括数据和节点)连接起来形成的数据结构
* 存储形式:地址 0x3638FD 0x1236FC 0x732E2
* $123$0x1236FC $456$0x732E2 $789$null
* ↑ ↑
* 节点的数据 链接地址
* 使用场景1、获取元素内容为456的元素,通过从第1个节点组合开始找
* 使用场景2、在元素内容为456的元素后添加一个元素内容为666的元素,操作步骤如下:
* A:把元素内容为456的节点组合中链接的地址记录下来
* B:把内容为666的节点组合的地址赋给内容为456的节点组合,把456链接的地址改为666的地址
* C:把步骤A记录下来的链接地址赋给666的节点组合,让其链接
* 存储形式:地址 0x3638FD 0x1236FC 0x93512 0x732E2
* $123$0x1236FC $456$0x93512 $666$0x732E2 $789$null
* ↑ ↑
* 节点的数据 链接地址
* 使用场景3、删除内容为456的元素,操作步骤如下:
* A:把元素内容为456的节点组合中链接的地址记录下来
* B:把内容为456的节点组合删除掉
* C:把步骤A记录下来的链接地址赋值给内容为456的节点组合的前一个节点组合
* 存储形式:地址 0x3638FD 0x732E2
* $123$0x732E2 $789$null
* ↑ ↑
* 节点的数据 链接地址
*
* 链表结构的特点:查找比较低效、增删比较高效
*/ // 类 ArrayList:List 接口的大小可变数组的实现。可以理解为Array(数组)形式的List
ArrayList arrayList = new ArrayList(); arrayList.add("China");
arrayList.add("USA"); System.out.println("ArrayList:" + arrayList); // ArrayList:[China, USA] // 使用迭代器进行遍历
Iterator iterator = arrayList.iterator(); while (iterator.hasNext()) {
String item = (String) iterator.next();
System.out.println(item);
} // 不使用迭代器进行遍历(使用size方法 和 get方法)
for (int i = 0; i < arrayList.size(); i++) {
String item = (String) arrayList.get(i);
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator; public class Sample13 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(); arrayList.add(new Student("张三", 20));
arrayList.add(new Student("李四", 18)); System.out.println("arrayList:" + arrayList); // 使用迭代器进行遍历
Iterator iterator = arrayList.iterator(); while (iterator.hasNext()) {
Student item = (Student) iterator.next();
System.out.println(item);
} // 不使用迭代器进行遍历(使用size方法 和 get方法)
for (int i = 0; i < arrayList.size(); i++) {
Student item = (Student) arrayList.get(i);
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator; public class Sample14 {
public static void main(String[] args) {
/*
* List自身特有的常用成员方法:
*
* ListIterator listIterator() :返回此列表元素的列表迭代器(按适当顺序)。
*
* ListIterator接口,继承自Iterator接口,是列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。 因为继承,自然有hasNext()和next()
*
* 1、boolean hasPrevious() :如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。 2、Object previous() :返回列表中的前一个元素。
*/
List list = new ArrayList();
list.add("大学");
list.add("中庸");
list.add("论语");
list.add("孟子"); ListIterator listIterator = list.listIterator(); // 从头至尾迭代
// while (listIterator.hasNext()) {
// String item = (String) listIterator.next();
// System.out.println(item);
// } System.out.println("---------------------------"); // Object obj1 = listIterator.previous();
// System.out.println(obj1);
// Object obj2 = listIterator.previous();
// System.out.println(obj2); // 迭代器中有cursor(游标)对象,上述的操作,使得游标移动到了列表集合的最后,所以可以再向前进行迭代了
// 从尾至头迭代
while (listIterator.hasPrevious()) {
String item = (String) listIterator.previous();
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator; public class Sample15 {
public static void main(String[] args) {
// 需求:向一个list集合中放入一些字符串,并进行遍历,便历时,如果找到"周瑜",就往集合list中添加一个字符串"诸葛亮"
List list = new ArrayList(); list.add("鲁肃");
list.add("周瑜");
list.add("吕蒙"); System.out.println("list:" + list); // Iterator iterator = list.iterator(); // java.util.ConcurrentModificationException 并发修改异常:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
// 并发:一并发生(一起发生),这里指:一边使用迭代器对list集合进行遍历,一边又向list集合中添加元素
// 类比:对着电风扇吹气,电风扇后面的人感觉不到吹进来的气的,因为吹的气都被电风扇的叶片击飞
// 也就是迭代器搞不清楚到底要迭代多少个元素,因为元素在发生着变化
// while (iterator.hasNext()) {
// String item = (String) iterator.next();
// if (item.equals("周瑜")) {
// list.add("诸葛亮");
// }
// } // 解决思路1:考虑把对list集合遍历的事情和往list集合中添加元素的事情都交给迭代器来做,自然要去看看迭代器有没有添加元素的方法
// Iterator没有该方法,但是其子接口ListIterator有
// 类比:在电风扇的叶片上开孔,伴随着叶片的旋转向后吹气,这样后面的人应该可以感觉到吹来的气的
ListIterator listIterator = list.listIterator(); while (listIterator.hasNext()) {
String item = (String) listIterator.next();
if (item.equals("周瑜")) {
// void add(Object obj)将指定的元素插入列表(可选操作)。
// 该元素直接插入到 next 返回的下一个元素的前面(如果有),或者 previous 返回的下一个元素之后(如果有);如果列表没有元素,那么新元素就成为列表中的唯一元素。
// 新元素被插入到隐式光标前:不影响对 next 的后续调用,并且对 previous 的后续调用会返回此新元素(此调用把调用 nextIndex 或 previousIndex 所返回的值增加 1)。
listIterator.add("诸葛亮");
// 下句会产生死循环么?不会,因为游标伴随着元素的添加,也向后进行了移动,也就是说不影响对 next 的后续调用
// listIterator.add("周瑜");
}
} // 解决思路2:不依靠迭代器,也可以遍历(依靠list对象的size()方法和get()方法),
// 这样的遍历可以理解为依靠外力的遍历,从list集合中把元素一个一个的取出来,对list集合来说,自身有多少元素自己最清楚,再添加新的元素也没有问题
// 这时不存在使用迭代器去遍历,也就没有对迭代器来说,搞不清楚到底要迭代多少个元素的问题
// for (int i = 0; i < list.size(); i++) {
// String item = (String) list.get(i);
// if (item.equals("周瑜")) {
// //boolean add(Object obj) :向列表的尾部添加指定的元素(可选操作)。
// list.add("诸葛亮");
// }
// } System.out.println("list:" + list);
}
}
 package cn.temptation;

 import java.util.Enumeration;
import java.util.Vector; public class Sample16 {
public static void main(String[] args) {
/*
* Vector类:向量类,可以实现可增长的对象数组。
*
* 从以下版本开始: JDK1.0
*
* Vector类的常用成员方法:
* 1、添加功能
* boolean add(E e) :将指定元素添加到此向量的末尾。
* void addElement(E obj) :将指定的组件添加到此向量的末尾,将其大小增加 1。
*
* 2、获取功能
* E get(int index) :返回向量中指定位置的元素。
* E elementAt(int index) :返回指定索引处的组件。
* Enumeration<E> elements() :返回此向量的组件的枚举。
*
* 接口 Enumeration:枚举器
* 注:此接口的功能与 Iterator 接口的功能是重复的。
*
* 接口 Iterator:迭代器
* 从以下版本开始: JDK1.2,作为Enumeration接口的升级版
*
* ArrayList类,从以下版本开始: JDK1.2,作为Vector类的升级版
*
*/ Vector vector = new Vector(); vector.add("中国");
vector.addElement("美国"); System.out.println("vector:" + vector); // vector:[中国, 美国] // 遍历
for (int i = 0; i < vector.size(); i++) {
String item = (String) vector.get(i);
System.out.println(item);
} for (int i = 0; i < vector.size(); i++) {
String item = (String) vector.elementAt(i);
System.out.println(item);
} // 使用枚举器进行枚举
Enumeration enumeration = vector.elements(); while (enumeration.hasMoreElements()) {
String item = (String) enumeration.nextElement();
System.out.println(item);
}
}
}
 package cn.temptation;

 import java.util.LinkedList;

 public class Sample17 {
public static void main(String[] args) {
/*
* 类 LinkedList:List 接口的链接列表实现。
*
* LinkedList类的常用成员方法:
* 1、添加功能
* void addFirst(E e) :将指定元素插入此列表的开头。
* void addLast(E e) :将指定元素添加到此列表的结尾。
*
* 2、获取功能
* E getFirst() :返回此列表的第一个元素。
* E getLast() :返回此列表的最后一个元素。
*
* 3、删除功能
* E removeFirst() :移除并返回此列表的第一个元素。
* E removeLast() :移除并返回此列表的最后一个元素。
*
*/
LinkedList linkedList = new LinkedList(); linkedList.add("中国"); linkedList.addFirst("美国");
linkedList.addLast("日本"); System.out.println("linkedList:" + linkedList); // linkedList:[美国, 中国, 日本] System.out.println(linkedList.getFirst()); // 美国
System.out.println(linkedList.getLast()); // 日本 System.out.println(linkedList.removeFirst()); // 美国
System.out.println(linkedList.removeLast()); // 日本 System.out.println("linkedList:" + linkedList); // linkedList:[中国]
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator; public class Sample18 {
public static void main(String[] args) {
// 需求:使用ArrayList类的成员方法实现在ArrayList集合对象中的一系列字符串进行检查,去除重复的字符串
// 例如:ArrayList:["中国","美国","日本","美国"] -----> ArrayList:["中国","美国","日本"] // 思路1:
// 1、创建一个新的容器
// 2、使用迭代器遍历旧的容器,获取到一个一个的元素
// 3、使用ArrayList类的contains方法对新容器进行检查,如果新容器中没有这个元素,就把这个元素放入到新的容器中;否则就不放入新的容器
// 4、这样遍历一遍旧容器中的所有元素,自然在新容器中的就是不重复的元素了 ArrayList oldList = new ArrayList(); oldList.add("中国");
oldList.add("美国");
oldList.add("日本");
oldList.add("美国");
oldList.add("美国");
oldList.add("中国"); System.out.println("oldList:" + oldList); // oldList:[中国, 美国, 日本, 美国] ArrayList newList = new ArrayList(); Iterator iterator = oldList.iterator(); while (iterator.hasNext()) {
String item = (String) iterator.next(); if (!newList.contains(item)) { // 新容器中不包含遍历出来的旧容器中的元素
newList.add(item);
}
} System.out.println("newList:" + newList); // newList:[中国, 美国, 日本]
}
}
 package cn.temptation;

 import java.util.ArrayList;

 public class Sample19 {
public static void main(String[] args) {
// 需求:使用ArrayList类的成员方法实现在ArrayList集合对象中的一系列字符串进行检查,去除重复的字符串
// 例如:ArrayList:["中国","美国","日本","美国"] -----> ArrayList:["中国","美国","日本"] // 思路2:
// 1、从第一个元素开始,把第一个元素拿出来,依次后后续的元素进行比较,如果有相同的,则删除之
// 2、从第二个元素开始,把第二个元素拿出来,依次后后续的元素进行比较,如果有相同的,则删除之.....
// n-1、从第n-1个元素开始,把第n-1个元素拿出来,依次后后续的元素进行比较,如果有相同的,则删除之 ArrayList arrayList = new ArrayList(); arrayList.add("中国");
arrayList.add("美国");
arrayList.add("日本");
arrayList.add("美国");
arrayList.add("美国");
arrayList.add("中国"); System.out.println("arrayList:" + arrayList); // arrayList:[中国, 美国, 日本, 美国] // for (int i = 1; i < arrayList.size(); i++) {
// if (arrayList.get(0).equals(arrayList.get(i))) {
// arrayList.remove(i);
// }
// }
//
// for (int i = 2; i < arrayList.size(); i++) {
// if (arrayList.get(1).equals(arrayList.get(i))) {
// arrayList.remove(i);
// }
// }
//
// ... // 错误写法:
// 现象:如下写法会漏掉删除第三个"美国"字符串
// 原因:因为remove,造成了arrayList对象的长度发生了改变,进而导致元素的索引发生了变化,所以理应同步调整索引
// for (int i = 0; i < arrayList.size() - 1; i++) { // 从第一个元素到第n-1个元素都要做这样的比较
// for (int j = i + 1; j < arrayList.size(); j++) {
// if (arrayList.get(i).equals(arrayList.get(j))) {
// arrayList.remove(j);
// }
// }
// } // 正确写法:
for (int i = 0; i < arrayList.size() - 1; i++) { // 从第一个元素到第n-1个元素都要做这样的比较
for (int j = i + 1; j < arrayList.size(); j++) {
if (arrayList.get(i).equals(arrayList.get(j))) {
arrayList.remove(j);
// 索引同步
j--;
}
}
} System.out.println("arrayList:" + arrayList);
}
}
 package cn.temptation;

 import java.util.ArrayList;
import java.util.Iterator; public class Sample20 {
public static void main(String[] args) {
// 需求:使用ArrayList类的成员方法实现对在ArrayList集合对象中的一系列学生对象进行检查,去除重复的学生对象
// 例如:ArrayList集合中存放两个 姓名为张三,年龄为20岁的学生对象,能够去除一个重复的 // 思路1:
// 1、创建一个新的容器
// 2、使用迭代器遍历旧的容器,获取到一个一个的元素
// 3、使用ArrayList类的contains方法对新容器进行检查,如果新容器中没有这个元素,就把这个元素放入到新的容器中;否则就不放入新的容器
// 4、这样遍历一遍旧容器中的所有元素,自然在新容器中的就是不重复的元素了 ArrayList oldList = new ArrayList(); oldList.add(new Student("张三", 20));
oldList.add(new Student("李四", 22));
oldList.add(new Student("王五", 18));
oldList.add(new Student("张三", 20)); // 遍历旧的容器
Object[] oldArr = oldList.toArray(); for (int i = 0; i < oldArr.length; i++) {
Student temp = (Student) oldArr[i];
System.out.println(temp);
} System.out.println("-------------------------------------------"); ArrayList newList = new ArrayList(); // 遍历
Iterator iterator = oldList.iterator(); while (iterator.hasNext()) {
Student item = (Student) iterator.next(); // 问题:为什么去重字符串有效?去重自定义对象就无效了呢?
// 解决方案:查看contains方法的源码
if (!newList.contains(item)) {
newList.add(item);
}
} // 遍历新的容器
Object[] newArr = newList.toArray(); for (int i = 0; i < newArr.length; i++) {
Student temp = (Student) newArr[i];
System.out.println(temp);
}
}
}
// 查看ArrayList类的源码
// 通过分析源码,发现contains方法起作用的是if (o.equals(elementData[i]))这句代码,也就是说关键在于equals方法
// 回顾以前说的内容,对于引用数据类型的对象,如果自身不重写equals方法,使用的是Object类的equals方法,也就是去比较对象的地址是否相同
// 回想一下,字符串重写equals方法,所以字符串的equals方法比较的是字符串对象的内容
// 这里比较自定义对象的内容,所以考虑重写自定义对象的equals方法 //public boolean contains(Object o) {
// return indexOf(o) >= 0;
//} //public int indexOf(Object o) {
// if (o == null) {
// for (int i = 0; i < size; i++)
// if (elementData[i]==null)
// return i;
// } else {
// for (int i = 0; i < size; i++)
// if (o.equals(elementData[i]))
// return i;
// }
// return -1;
//}
 package cn.temptation;

 import java.util.ArrayList;

 public class Sample21 {
public static void main(String[] args) {
// 需求:使用ArrayList类的成员方法实现对在ArrayList集合对象中的一系列学生对象进行检查,去除重复的学生对象
// 例如:ArrayList集合中存放两个 姓名为张三,年龄为20岁的学生对象,能够去除一个重复的 // 思路2:
// 1、从第一个元素开始,把第一个元素拿出来,依次后后续的元素进行比较,如果有相同的,则删除之
// 2、从第二个元素开始,把第二个元素拿出来,依次后后续的元素进行比较,如果有相同的,则删除之.....
// n-1、从第n-1个元素开始,把第n-1个元素拿出来,依次后后续的元素进行比较,如果有相同的,则删除之 ArrayList list = new ArrayList(); list.add(new Student("张三", 20));
list.add(new Student("李四", 22));
list.add(new Student("王五", 18));
list.add(new Student("张三", 20)); // 遍历容器
Object[] arr = list.toArray(); for (int i = 0; i < arr.length; i++) {
Student temp = (Student) arr[i];
System.out.println(temp);
} System.out.println("-------------------------------------------"); for (int i = 0; i < list.size() - 1; i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) {
// 因为ArrayList对象的get方法获取的是Student类类型的对象,该对象已经进行了equals方法的重写
list.remove(j);
// 同步索引
j--;
}
}
} // 遍历容器
arr = list.toArray(); for (int i = 0; i < arr.length; i++) {
Student temp = (Student) arr[i];
System.out.println(temp);
}
}
}
 package cn.temptation;

 public class Student {
// 成员变量
private String name;
private int age; // 构造函数
public Student() {
super();
} public Student(String name, int age) {
super();
this.name = name;
this.age = 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;
} @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;
Student other = (Student) 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;
} @Override
public String toString() {
return "学生 [姓名为:" + name + ", 年龄为:" + age + "]";
}
}
 package cn.temptation;

 import java.util.Iterator;
import java.util.LinkedList; public class Sample22 {
public static void main(String[] args) {
// 数据结构:栈结构
// 特点:先进后出、后进先出
// 举例:弹夹中的子弹、杯子中的水 // 需求:运用学过的集合知识,模拟一下栈的效果 // 思路:
// 因为"先进后出、后进先出",所以容器存放数据是有序的,这种有序的容器让我们选择实现List接口的集合
// 那么在考虑List接口的实现类ArrayList、Vector、LinkedList这三个,考虑这三个类放入数据的顺序和取出数据的顺序一致,如何实现"先进后出、后进先出"的效果?
// 联系到LinkedList这个实现类,可以在放入数据时玩一个花样,即放入时就排好取出时的顺序(使用一系列和first、last相关的方法) LinkedList linkedList = new LinkedList(); // 下面两句效果相同
// linkedList.add("中国");
linkedList.addFirst("中国");
linkedList.addFirst("美国");
linkedList.addFirst("日本"); System.out.println("linkedList:" + linkedList); Iterator iterator = linkedList.iterator(); while (iterator.hasNext()) {
String item = (String) iterator.next();
System.out.println(item);
}
}
}
 package cn.temptation;

 public class Sample23 {
public static void main(String[] args) {
// 需求:制作一个自定义类(Stack),实现栈的功能,有入栈功能、出栈功能、显示元素功能、判断栈中是否为空功能 Stack stack = new Stack(); // 入栈
stack.push("China");
stack.push("USA");
stack.push("Japan"); System.out.println("入栈后:" + stack); // 入栈后:栈 ----->[Japan, USA, China] // 出栈
// System.out.println(stack.pop()); // Japan
// System.out.println(stack.pop()); // USA
// System.out.println(stack.pop()); // China
// // 执行异常
// System.out.println(stack.pop()); // 重复的事情反复做很傻,且还会产生异常
while (!stack.isEmpty()) {
System.out.println(stack.pop());
} System.out.println("出栈后:" + stack);
}
}
 package cn.temptation;

 import java.util.LinkedList;

 /**
* 自定义的栈类
*/
public class Stack {
// 成员变量
private LinkedList linkedList = new LinkedList(); // 成员方法 // 显示元素(重写toString方法)
@Override
public String toString() {
return "栈 ----->" + linkedList;
} // 入栈
public void push(Object obj) {
// 如果单纯只考虑push方法,可以就在方法中声明局部变量的LinkedList类型的对象,
// 但是不同的成员方法都会使用到LinkedList类型的对象,所以这里局部变量就应该升级为类中均可访问的成员变量
// LinkedList linkedList = new LinkedList(); linkedList.addFirst(obj);
} // 出栈
public Object pop() {
// 写法1
// 1、通过getFirst方法获取到集合中的第一个元素
// 2、通过remove方法移除集合中的第一个元素
// 3、返回获取到的第一个元素
// Object temp = linkedList.getFirst();
// linkedList.remove();
// return temp; // 写法2
return linkedList.removeFirst();
} // 判断是否为空
public boolean isEmpty() {
// 写法1
// return linkedList.size() == 0; // 写法2:继承自AbstractCollection类中的成员方法isEmpty()
return linkedList.isEmpty();
}
}
 package cn.temptation;

 import java.util.Stack;

 public class Sample24 {
public static void main(String[] args) {
// 类 Stack:Stack 类表示后进先出(LIFO)的对象堆栈。
Stack stack = new Stack(); // 入栈
stack.push("China");
stack.push("USA");
stack.push("Japan"); System.out.println("入栈后:" + stack); while (!stack.isEmpty()) {
System.out.println(stack.pop());
} System.out.println("出栈后:" + stack);
}
}