集合:集合是存储对象数据的集合容器。
集合比数组的优势:
1. 集合可以存储任意类型的对象数据,数组只能存储同一种数据类型 的数据。
2. 集合的长度是会发生变化的,数组的长度是固定的。
单列集合体系:
---------| Collection 单例集合的根接口
------------| List 如果是实现了List接口的集合类, 具备的特点:有序,重复。
---------------| ArraryList 底层 是使用了Object数组实现的,特点: 查询速度快,增删慢。
---------------| LinkedList 底层是使用了链表数据结构实现 的, 特点: 查询速度慢,增删快。
---------------| Vector Vector的实现与ArrayList是一致,但是是线程安全 的,操作效率低。 jdk1.0的时候出现的
------------| Set 如果是实现了Set接口的集合类,具备的特点:无序,不可重复。
----------------| HashSet 底层是使用了一个哈希表支持的, 特点:存取速度快。
----------------| TreeSet 底层是使用了红黑树(二叉树)数据结构实现的, 特点:会对元素进行排序存储。
凡是容器都具有增删改查的功能和对应的方法。
collection接口中的方法:
增加:
boolean add(E e)
确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)
将指定
collection 中的所有元素都添加到此 collection 中(可选操作)。
删除:
void clear()
移除此 collection 中的所有元素(可选操作)。
boolean remove(Object o)
从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
boolean retainAll(Collection<?> c)
仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
查看:
int size()
返回此 collection 中的元素数。
判断:
boolean isEmpty()
如果此 collection 不包含元素,则返回 true。
boolean contains(Object o)
如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c)
如果此 collection 包含指定 collection 中的所有元素,则返回 true。
迭代:
Object[]
toArray()
返回包含此 collection 中所有元素的数组。
Iterator<E> iterator()
返回在此 collection 的元素上进行迭代的迭代器。
迭代器的方法:
boolean hasNext()
如果仍有元素可以迭代,则返回 true。
void remove()
从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。只能用在调用next方法之后,否则会报异常:java.lang.IllegalStateException
代码示例如下:
1 import java.util.ArrayList; 2 import java.util.Arrays; 3 import java.util.Collection; 4 import java.util.Iterator; 5 6 public class DemoCollection { 7 8 public static void main(String[] args) { 9 //加入 10 Collection<String> collection = new ArrayList<String>(); 11 System.out.println("加入元素是否成功?"+ collection.add("张三")); 12 collection.add("李四"); 13 System.out.println("add之后的collection"+collection); 14 15 Collection<String> collection2 = new ArrayList<String>(); 16 collection2.add("王五"); 17 collection2.add("赵六"); 18 collection.addAll(collection2); 19 System.out.println("addAll之后的collection"+collection); 20 //删除 21 System.out.println("删除是否成功?"+collection2.remove("赵六1")); 22 System.out.println("删除是否成功?"+collection2.remove("赵六")); 23 System.out.println("remove之后的collection2"+collection2); 24 System.out.println("删除是否成功?"+collection.removeAll(collection2)); 25 System.out.println("removeAll之后的collection"+collection); 26 27 Collection<String> collection3 = new ArrayList<String>(); 28 collection3.add("赵六"); 29 System.out.println("删除是否成功?"+collection.retainAll(collection3)); 30 System.out.println("retainAll之后的"+collection); 31 32 collection2.clear(); 33 System.out.println("clear之后的collection2?"+collection2); 34 //查看 35 System.out.println("collection的元素个数:"+collection.size()); 36 //判断 37 System.out.println("collection时候为空?"+collection.isEmpty()); 38 System.out.println("collection是否包含赵六?"+collection.contains("赵六")); 39 System.out.println("collection是否包含collection3?"+collection.containsAll(collection3)); 40 //迭代 41 Object[] array = collection.toArray(); 42 System.out.println(Arrays.toString(array)); 43 44 Iterator<String> iterator = collection.iterator(); 45 while (iterator.hasNext()) { 46 System.out.println(iterator.next()); 47 } 48 49 Iterator<String> iterator2 = collection.iterator(); 50 iterator2.next(); 51 iterator2.remove(); 52 System.out.println("collection中的"+collection); 53 } 54 55 }
List接口特有的方法:
增加:
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection<? extends E> c)
将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
修改:
E
set(int index, E element)
用指定元素替换列表中指定位置的元素(可选操作)。
查看:
E
get(int index)
返回列表中指定位置的元素。
int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
int lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
List<E>
subList
(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和
toIndex(不包括)之间的部分视图。
迭代器:
ListIterator<E>
listIterator()
返回此列表元素的列表迭代器(按适当顺序)。
ListIterator<E>
listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
ListIterator接口特有的方法:
boolean hasPrevious()
如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
void add(E e)
将指定的元素插入列表(可选操作)。意思是把当前有元素插入到当前指针指向的位置上。
void set(E e)
用指定元素替换
next 或 previous 返回的最后一个元素(可选操作)。
迭代器在变量元素的时候要注意事项:
1、在迭代器迭代元素 的过程中,不允许使用集合对象改变集合中的元素 个数,如果需要添加或者删除只能使用迭代器的方法进行操作。
2、如果使用过了集合对象改变集合中元素个数那么就会出现ConcurrentModificationException异常。
迭代元素的过程中: 迭代器创建到使用结束的时间。
代码示例如下:
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.ListIterator; 4 5 public class DemoList { 6 public static void main(String[] args) { 7 List<String> list = new ArrayList<String>(); 8 //增加 9 list.add(0, "张三"); 10 System.out.println(list); 11 List<String> list2 = new ArrayList<String>(); 12 list2.add("李四"); 13 list2.add("王五"); 14 list.addAll(1, list2); 15 System.out.println(list); 16 //修改 17 list.set(2, "赵六"); 18 System.out.println(list); 19 //查看 20 System.out.println("索引为0的元素:"+list.get(0)); 21 System.out.println("李四的索引为:"+list.indexOf("李四")); 22 list.add("张三"); 23 System.out.println("张三的索引为:"+list.indexOf("张三")); 24 System.out.println("张三最后一次出现的索引为:"+list.lastIndexOf("张三")); 25 26 List<String> list3 = list.subList(1, 3); 27 System.out.println(list3); 28 29 //迭代器 30 System.out.println(list); 31 ListIterator<String> listIterator = list.listIterator(); 32 while(listIterator.hasNext()){ 33 listIterator.add("哈哈"); 34 System.out.print(listIterator.next()+","); 35 // listIterator.set("=="); //只能用在next或者previous之后 36 } 37 System.out.println(); 38 System.out.println(list); 39 while(listIterator.hasPrevious()){ 40 list.remove("张三"); //在迭代中不能修改List,否则会报异常ConcurrentModificationException 41 System.out.print(listIterator.previous()+","); 42 } 43 } 44 }
ArrayList类特有的方法:
void ensureCapacity(int minCapacity)
如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
void trimToSize()
将此 ArrayList 实例的容量调整为列表的当前大小。
注意:ArrayList底层是维护了一个Object数组实现 的,使用无参构造函数时,Object数组默认的容量是10,当长度不够时,自动增长0.5倍。
需求: 编写一个函数清除集合中重复书籍,书号相等即为重复。
代码如下:
1 import java.util.ArrayList; 2 import java.util.ListIterator; 3 4 class Book{ 5 int id; 6 String name; 7 public Book(int id, String name) { 8 this.id = id; 9 this.name = name; 10 } 11 12 @Override 13 public boolean equals(Object obj) { 14 Book book = (Book) obj; 15 return this.id == book.id; 16 } 17 @Override 18 public int hashCode() { 19 return this.id; 20 } 21 22 @Override 23 public String toString() { 24 return "[编号:"+this.id +"书名:"+this.name+"]"; 25 } 26 } 27 28 29 public class DemoList { 30 public static void main(String[] args) { 31 ArrayList<Book> list = new ArrayList<Book>(); 32 list.add(new Book(110, "西游记")); 33 list.add(new Book(220, "水浒传")); 34 list.add(new Book(110, "西门庆与潘金莲")); 35 System.out.println(list); 36 System.out.println(clearRepeat(list)); 37 } 38 39 public static ArrayList<Book> clearRepeat(ArrayList<Book> arrayList) { 40 ArrayList<Book> newList = new ArrayList<Book>(); 41 ListIterator<Book> listIterator = arrayList.listIterator(); 42 while(listIterator.hasNext()){ 43 Book book = listIterator.next(); 44 if (!newList.contains(book)) { 45 newList.add(book); 46 } 47 } 48 return newList; 49 } 50 }
LinkList类特有的方法:
增加:
void addFirst(E e)
将指定元素插入此列表的开头。
void addLast(E e)
将指定元素添加到此列表的结尾。
删除:
E
removeFirst()
移除并返回此列表的第一个元素。
E
removeLast()
移除并返回此列表的最后一个元素。
查看:
逆序迭代器:
Iterator<E>
descendingIterator()
返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
与数据结构相关的函数:
1:栈 (1.6) : 主要是用于实现堆栈数据结构的存储方式。
先进后出
void push(E e)
将元素推入此列表所表示的堆栈。
E
pop()
从此列表所表示的堆栈处弹出一个元素。
2:队列(双端队列1.5): 主要是为了让你们可以使用LinkedList模拟队列数据结构的存储方式。
先进先出
boolean offer(E e)
将指定元素添加到此列表的末尾(最后一个元素)。
E
poll()
获取并移除此列表的头(第一个元素)
代码示例如下:
1 public class DemoList { 2 public static void main(String[] args) { 3 LinkedList<String> list = new LinkedList<String>(); 4 //增加 5 list.add("李四"); 6 list.addFirst("张三"); 7 list.addLast("王五"); 8 System.out.println(list); 9 //查看 10 System.out.println(list.getFirst()); 11 System.out.println(list.getLast()); 12 //逆序构造器 13 Iterator<String> iterator = list.descendingIterator(); 14 while(iterator.hasNext()){ 15 System.out.println(iterator.next()); 16 } 17 //删除 18 list.removeLast(); 19 System.out.println(list); 20 list.removeFirst(); 21 System.out.println(list); 22 //与数据结构 23 //栈 24 list.push("战三"); 25 System.out.println(list); 26 list.pop(); 27 System.out.println(list); 28 //队列 29 list.offer("张三"); 30 System.out.println(list); 31 list.poll(); 32 System.out.println(list); 33 34 } 35 }
需求:使用LinkedList实现堆栈数据结构的存储方式与队列的数据结构存储方式。
代码如下:
1 class StackList<T>{ 2 LinkedList<T> list; 3 4 public StackList() { 5 this.list = new LinkedList<T>(); 6 } 7 8 public void push(T t) { 9 this.list.addFirst(t); 10 } 11 12 public T pop() { 13 return this.list.removeFirst(); 14 } 15 16 @Override 17 public String toString() { 18 return list.toString(); 19 } 20 21 } 22 23 class QueueList<T>{ 24 LinkedList<T> list; 25 26 public QueueList() { 27 this.list = new LinkedList<T>(); 28 } 29 30 public boolean offer(T t) { 31 return this.list.offer(t); 32 } 33 34 public T poll() { 35 return this.list.poll(); 36 } 37 @Override 38 public String toString() { 39 return this.list.toString(); 40 } 41 } 42 43 public class DemoList { 44 public static void main(String[] args) { 45 StackList<String> stackList = new StackList<String>(); 46 stackList.push("张三"); 47 stackList.push("李四"); 48 stackList.push("王五"); 49 System.out.println(stackList); 50 stackList.pop(); 51 System.out.println(stackList); 52 53 QueueList<String> queueList = new QueueList<String>(); 54 queueList.offer("张三"); 55 queueList.offer("李四"); 56 queueList.offer("王五"); 57 System.out.println(queueList); 58 queueList.poll(); 59 System.out.println(queueList); 60 61 } 62 }
需求: 使用LinkedList存储一副扑克牌,然后实现洗牌功能。
1 //扑克类 2 class Poker{ 3 4 String color; //花色 5 String num; //点数 6 7 public Poker(String color, String num) { 8 super(); 9 this.color = color; 10 this.num = num; 11 } 12 13 @Override 14 public String toString() { 15 return "{"+color+num+"}"; 16 } 17 } 18 19 public class Demo2 { 20 21 public static void main(String[] args) { 22 LinkedList pokers = createPoker(); 23 shufflePoker(pokers); 24 showPoker(pokers); 25 } 26 27 //洗牌的功能 28 public static void shufflePoker(LinkedList pokers){ 29 //创建随机数对象 30 Random random = new Random(); 31 for(int i = 0 ; i <100; i++){ 32 //随机产生两个索引值 33 int index1 = random.nextInt(pokers.size()); 34 int index2 = random.nextInt(pokers.size()); 35 //根据索引值取出两张牌,然后交换两张牌的顺序 36 Poker poker1 = (Poker) pokers.get(index1); 37 Poker poker2 = (Poker) pokers.get(index2); 38 pokers.set(index1, poker2); 39 pokers.set(index2, poker1); 40 } 41 } 42 43 //显示扑克牌 44 public static void showPoker(LinkedList pokers){ 45 for(int i = 0 ; i<pokers.size() ; i++){ 46 System.out.print(pokers.get(i)); 47 //换行 48 if(i%13==12){ 49 System.out.println(); 50 } 51 } 52 } 53 54 //生成扑克牌的方法 55 public static LinkedList createPoker(){ 56 //该集合用于存储扑克对象。 57 LinkedList list = new LinkedList(); 58 //定义数组存储所有的花色与点数 59 String[] colors = {"黑桃","红桃","梅花","方块"}; 60 String[] nums = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"}; 61 for(int i = 0 ; i < colors.length ; i++){ 62 for(int j = 0 ; j<nums.length ; j++){ 63 list.add(new Poker(colors[i], nums[j])); 64 } 65 } 66 return list; 67 } 68 }
笔试题: 说出ArrayLsit与Vector的区别?
相同点: ArrayList与Vector底层都是使用了Object数组实现的。
不同点:
1. ArrayList是线程不同步的,操作效率高。
Vector是线程同步的,操作效率低。
2. ArrayList是JDK1.2出现,Vector是jdk1.0的时候出现的。
set接口没有特有的方法
set中的元素是无序不可重复的。
hashSet的实现原理:底层是使用了一个哈希表支持的。
往Haset添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值 ,然后通过元素 的哈希值经过移位等运算,就可以算出该元素在哈希表中的存储位置。存储过程中有一下两种情况。
情况1: 如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上。
情况2: 如果算出该元素的存储位置目前已经存在有其他的元素了,那么会调用该元素的equals方法与该位置的元素再比较一次,如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素,不添加,如果equals方法返回的是false,那么该元素允许添加。
需求:接受键盘录入用户名和密码来进行用户注册。如果用户名和密码已经存在,则不能完成注册。如果不存在,则注册成功。
代码示例如下:
1 import java.util.HashSet; 2 import java.util.Scanner; 3 4 //接受键盘录入用户名和密码来进行用户注册。如果用户名和密码已经存在,则不能完成注册。如果不存在,则注册成功。 5 class User{ 6 String userName; 7 String password; 8 public User(String userName, String password) { 9 this.userName = userName; 10 this.password = password; 11 } 12 13 @Override 14 public int hashCode() { 15 // 如果两个字符串的内容一致,那么返回的hashCode 码肯定也会一致的。 16 return this.userName.hashCode() + this.password.hashCode(); 17 } 18 19 @Override 20 public boolean equals(Object obj) { 21 User user = (User)obj; 22 return this.userName.equals(user.userName) && this.password.equals(user.password); 23 } 24 25 @Override 26 public String toString() { 27 28 return "当前用户名:"+this.userName + "密码:"+this.password; 29 } 30 31 } 32 33 public class Set { 34 public static void main(String[] args) { 35 Scanner scanner = new Scanner(System.in); 36 HashSet<User> set = new HashSet<User>(); 37 while(true){ 38 System.out.println("请输入账号:"); 39 String userName = scanner.next(); 40 System.out.println("请输入密码:"); 41 String password = scanner.next(); 42 User user = new User(userName, password); 43 44 if (set.add(user)) { 45 System.out.println("注册成功"); 46 System.out.println(set); 47 }else{ 48 System.out.println("注册失败"); 49 } 50 } 51 } 52 }
treeSet
内部实现:
底层是使用了红黑树(二叉树)数据结构实现的, 特点:会对元素进行排序存储
注意事项:
1. 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。
2. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素
的比较规则定义在compareTo(T o)方法上。
3. 如果比较元素的时候,compareTo方法返回 的是0,那么该元素就被视为重复元素,不允许添加.(注意:TreeSet与HashCode、equals方法是没有任何关系。)
4. 往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序 的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。
5. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口, 在创建TreeSet对象的时候也传入了比较器,那么是以比较器的比较规则优先使用。
如何自定义定义比较器:
自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可。
自定义比较器的格式 :
class 类名 implements Comparator{
}
推荐使用:使用比较器(Comparator)。
TreeSet存储具备自然顺序的元素,代码示例如下:
1 public class Set { 2 3 public static void main(String[] args) { 4 TreeSet<Integer> treeSet = new TreeSet<Integer>(); 5 treeSet.add(1); 6 treeSet.add(10); 7 treeSet.add(8); 8 treeSet.add(3); 9 treeSet.add(2); 10 System.out.println(treeSet); 11 } 12 }
TreeSet存储不具备自然顺序的元素,代码示例如下:
当前类实现Comparable接口和public int compareTo(Object o)方法
1 class User implements Comparable<User>{ 2 Integer id; 3 String userName; 4 String password; 5 public User(Integer id, String userName, String password) { 6 this.id = id; 7 this.userName = userName; 8 this.password = password; 9 } 10 11 @Override 12 public int compareTo(User o) { 13 User user = (User)o; 14 return this.id - user.id; 15 } 16 17 @Override 18 public String toString() { 19 return "id:"+ this.id +" 名字:"+this.userName ; 20 } 21 22 } 23 24 public class Set { 25 26 public static void main(String[] args) { 27 TreeSet<User> treeSet = new TreeSet<User>(); 28 treeSet.add(new User(110, "张三", "123")); 29 treeSet.add(new User(310, "王五", "123")); 30 treeSet.add(new User(210, "李四", "123")); 31 System.out.println(treeSet); 32 } 33 }
自定义比较器类
1 class User{ 2 Integer id; 3 String userName; 4 String password; 5 public User(Integer id, String userName, String password) { 6 this.id = id; 7 this.userName = userName; 8 this.password = password; 9 } 10 11 @Override 12 public String toString() { 13 return "id:"+ this.id +" 名字:"+this.userName ; 14 } 15 16 } 17 18 class myComparator implements Comparator<User>{ 19 20 @Override 21 public int compare(User o1, User o2) { 22 return o1.id - o2.id; 23 } 24 } 25 26 public class Set { 27 28 public static void main(String[] args) { 29 TreeSet<User> treeSet = new TreeSet<User>(new myComparator()); 30 treeSet.add(new User(110, "张三", "123")); 31 treeSet.add(new User(310, "王五", "123")); 32 treeSet.add(new User(210, "李四", "123")); 33 System.out.println(treeSet); 34 } 35 }