集合List,Set学习

This commit is contained in:
dingjiawen 2022-09-18 17:16:35 +08:00
parent 82812f32ff
commit 571f1185f5
5 changed files with 615 additions and 0 deletions

View File

@ -0,0 +1,92 @@
package com.markilue.java_learning.collection;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
/**
* @BelongsProject: java_learning
* @BelongsPackage: com.markilue.java_learning.collection
* @Author: dingjiawen
* @CreateTime: 2022-09-18 14:34
* @Description:
* TODO collection的addAll,add,retainAll方法
* 1addAll(另一个集合)方法会将单个元素都加进去
* 2add(另一个集合)方法会将其作为一个整体加入
* 3retainAll(另一个集合)方法会将两个集合的交集保留下来,其他的丢弃 =>注意不是返回一个新集合,而是改变原来的集合
* @Version: 1.0
*/
public class CollectionCommonFunction {
//addAll
@Test
public void test2(){
Collection coll = new ArrayList();
coll.add(1);
coll.add(2);
System.out.println("coll集合元素的个数" + coll.size()); //2
Collection other = new ArrayList();
other.add(1);
other.add(2);
other.add(3);
coll.addAll(other);
// coll.add(other);
System.out.println("coll集合元素的个数" + coll.size()); //5
for (Object o : coll) {
System.out.println(o);// 1 2 1 2 3
}
}
//add
@Test
public void test3(){
Collection coll = new ArrayList();
coll.add(1);
coll.add(2);
System.out.println("coll集合元素的个数" + coll.size()); //2
Collection other = new ArrayList();
other.add(1);
other.add(2);
other.add(3);
coll.add(other);
// coll.add(other);
System.out.println("coll集合元素的个数" + coll.size()); //3
for (Object o : coll) {
System.out.println(o);// 1 2 [1 2 3]
}
}
//retainAll
@Test
public void test5(){
Collection coll = new ArrayList();
coll.add(1);
coll.add(2);
coll.add(3);
coll.add(4);
coll.add(5);
System.out.println("coll集合元素的个数" + coll.size());//5
Collection other = new ArrayList();
other.add(1);
other.add(2);
other.add(8);
coll.retainAll(other);//保留交集
System.out.println("coll集合元素的个数" + coll.size());//2
for (Object o : coll) {
System.out.println(o); //1 2
}
}
}

View File

@ -0,0 +1,110 @@
package com.markilue.java_learning.collection;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
/**
* @BelongsProject: java_learning
* @BelongsPackage: com.markilue.java_learning.collection
* @Author: dingjiawen
* @CreateTime: 2022-09-18 14:50
* @Description:
* TODO iterator是一个可迭代接口,collection对象都实现了这个接口(java.util.Iterator)
* 1)其使用方法是:首先通过调用集合的iterator()方法获得迭代器对象然后使用hashNext()方法判断集合中是否存在下一个元素如果存在则调用next()方法将元素取出否则说明已到达了集合末尾停止遍历元素
* 内部是通过迭代器获取索引实现的:在调用Iterator的next方法之前迭代器的索引位于第一个元素之前不指向任何元素当第一次调用迭代器的next方法后迭代器的索引会向后移动一位指向第一个元素并将该元素返回当再次调用next方法时迭代器的索引会指向第二个元素并将该元素返回依此类推直到hasNext方法返回false表示到达了集合的末尾终止对元素的遍历
* 2)可以通过iterable对collection里的元素进行删除,相比于.remove()方法的好处是通过iterable的方式可以加上条件判断 =>使用方式iterator.remove
* 3)未实现java.util.Iterator的类如果想实现foreach等增强for循环的方式可以去实现java.lang.Iterable接口,具体方式见MyArrayList类
* 4)快速失败fail-fast机制: 在调用iterator方法获取迭代器操作时调用迭代器自身以外的方法对集合中的结构进行改变,如调用list.add()或remove()方法否则会报错ConcurrentModificationException
* 注意迭代器的快速失败行为不能得到保证一般来说存在不同步的并发修改时不可能作出任何坚决的保证快速失败迭代器尽最大努力抛出 `ConcurrentModificationException`
* 因此编写依赖于此异常的程序的方式是错误的正确做法是迭代器的快速失败行为应该仅用于检测 bug
* 实现方式:1)在ArrayList等集合类中都有一个modCount变量它用来记录集合的结构被修改的次数
* 2)当我们给集合添加和删除操作时会导致modCount++
* 3)然后当我们用Iterator迭代器遍历集合时创建集合迭代器的对象时用一个变量记录当前集合的modCount
* 例如`int expectedModCount = modCount;`并且在迭代器每次next()迭代元素时都要检查 `expectedModCount != modCount`
* 如果不相等了那么说明你调用了Iterator迭代器以外的Collection的add,remove等方法修改了集合的结构使得modCount++值变了就会抛出ConcurrentModificationException
* @Version: 1.0
*/
public class Iterable<E> {
//测试iterator.remove方法
@Test
public void test02(){
Collection<String> coll = new ArrayList<>();
coll.add("陈琦");
coll.add("李晨");
coll.add("邓超");
coll.add("黄晓明");
//删除名字有三个字的
// coll.remove(o)//无法编写
Iterator<String> iterator = coll.iterator();
while(iterator.hasNext()){
String element = iterator.next();
if(element.length()==3){
// coll.remove(element);//错误的
iterator.remove();
}
}
System.out.println(coll);
}
//测试继承了java.lang.Iterator的MyArrayList类
@Test
public void test(){
MyArrayList<String> my = new MyArrayList<String>();
my.add("hello");
my.add("java");
my.add("world");
my.add("atguigu");
my.add("list");
my.add("data");
for (String string : my) {
System.out.println(string);
}
}
@Test
public void test01() {
Collection<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.add("atguigu");
list.add("world");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
list.remove(iterator.next());
}
}
@Test
public void test03() {
ArrayList<String> list = new ArrayList<>();
list.add("hello");
list.add("java");
list.add("atguigu");
list.add("world");
//以下代码没有发生ConcurrentModificationException异常
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String str = iterator.next();
if("atguigu".endsWith(str)){
list.remove(str);
}
}
}
}

View File

@ -0,0 +1,88 @@
package com.markilue.java_learning.collection;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
/**
* @BelongsProject: java_learning
* @BelongsPackage: com.markilue.java_learning.collection
* @Author: dingjiawen
* @CreateTime: 2022-09-18 15:57
* @Description:
* TODO List的实现类:ArrayList,Vector,LinkedList
* 1)ArrayList:
* 1.数据存储的结构是数组结构元素增删慢查找快;
* 2.发生扩容时ArrayList扩容为原来的1.5倍;
* 3.初始化为长度为0的空数组之后在添加第一个元素时再创建长度为10的数组
* 2)Vector:
* 1.底层也用的是数组结构,线程安全效率低
* 2.发生扩容时Vector扩容为原来的2倍;
* 3.初始容量默认为10
* 4.支持Enumeration 迭代器但是该迭代器不支持快速失败面对并发的修改迭代器很快就完全失败
* 3)LinkedList:
* 1.数据存储的结构是链表结构(双向链表)方便元素添加删除的集合
* 2.LinkedList还实现了Deque接口为在列表的开头及结尾 getremove insert 元素提供了统一的命名方法这些操作允许将链接列表用作堆栈队列或双端队列
* 3.Stack与LinkedList都能作为栈结构对外表现的功能效果是一样但是它们的物理结构不同Stack的物理结构是顺序结构的数组而LinkedList的物理结构是链式结构的双向链表我们推荐使用LinkedList
* 4.每种方法都存在两种形式一种形式在操作失败时抛出异常(addremove,get)另一种形式返回一个特殊值null false具体取决于操作(offer,poll,peek)
*
* 4)ListTest 集合额外提供了一个 listIterator() 方法该方法返回一个 ListIterator 对象 ListIterator 接口继承了 Iterator 接口提供了专门操作 ListTest 的方法
* @Version: 1.0
*/
public class ListTest {
//LinkedList作为栈;使用addFirst和removeFirst方法
@Test
public void test(){
LinkedList<Integer> list = new LinkedList<>();
//入栈
list.addFirst(1);
list.addFirst(2);
list.addFirst(3);
//出栈 LIFO后进先出
System.out.println(list.removeFirst());//3
System.out.println(list.removeFirst());//2
System.out.println(list.removeFirst());//1
//栈空了会报异常java.util.NoSuchElementException
System.out.println(list.removeFirst());
}
//LinkedList作为队列;使用addLast和pollFirst方法
@Test
public void test1(){
LinkedList<Integer> list = new LinkedList<>();
//入队
list.addLast(1); //或者使用offerLast
list.addLast(2);
list.addLast(3);
//出队 FIFO先进先出
System.out.println(list.pollFirst());//1 //或者使用removeFirst
System.out.println(list.pollFirst());//2
System.out.println(list.pollFirst());//3
//队空了返回null
System.out.println(list.pollFirst());//null
}
//测试List中的listIterator迭代器方法
@Test
public void test2(){
List<String> c = new ArrayList<String>();
c.add("张三");
c.add("李四");
c.add("王五");
//从指定位置往前遍历
ListIterator<String> listIterator = c.listIterator(c.size());
while(listIterator.hasPrevious()){
String previous = listIterator.previous();
System.out.println(previous);
}
}
}

View File

@ -0,0 +1,57 @@
package com.markilue.java_learning.collection;
import java.util.Arrays;
import java.util.Iterator;
/**
* @BelongsProject: java_learning
* @BelongsPackage: com.markilue.java_learning.collection
* @Author: dingjiawen
* @CreateTime: 2022-09-18 15:13
* @Description: TODO 测试实现java.lang.Iterator类实现增强for
* @Version: 1.0
*/
public class MyArrayList<E> implements java.lang.Iterable<E> {
private Object[] array;
private int size;
public MyArrayList() {
array = new Object[5];
}
public void add(E e) {
ensureCapacityEnough();
array[size++] = e;
}
public void ensureCapacityEnough() {
if (size >= array.length) {
array = Arrays.copyOf(array, array.length * 2);
}
}
@Override
public Iterator<E> iterator() {
return new Iter();
}
private class Iter implements Iterator<E> {
int cursor;
@Override
public boolean hasNext() {
return cursor <= size;
}
@Override
public E next() {
return (E) array[cursor++];
}
}
}

View File

@ -0,0 +1,268 @@
package com.markilue.java_learning.collection;
import org.junit.Test;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;
/**
* @BelongsProject: java_learning
* @BelongsPackage: com.markilue.java_learning.collection
* @Author: dingjiawen
* @CreateTime: 2022-09-18 16:46
* @Description:
* TODO Set的三个实现类 HashSetLinkedHashSetTreeSet:
* Set接口是Collection的子接口set接口没有提供额外的方法但是比`Collection`接口更加严格了Set 集合不允许包含相同的元素如果试把两个相同的元素加入同一个 Set 集合中则添加操作失败
* 1)HashSet:
* 1.底层的实现其实是一个java.util.HashMap支持.底层物理实现是一个Hash表
* 2.HashSet 集合判断两个元素相等的标准两个对象通过 hashCode() 方法比较相等并且两个对象的 equals() 方法返回值也相等因此存储到HashSet的元素要重写hashCode和equals方法具体写法可以参照Employee类
* 2)LinkedHashSet
* 1.LinkedHashSet是HashSet的子类它在HashSet的基础上在结点中增加两个属性before和after维护了结点的前后添加顺序
* 2.`java.util.LinkedHashSet`它是链表和哈希表组合的一个数据存储结构LinkedHashSet插入性能略低于 HashSet但在迭代访问 Set 里的全部元素时有很好的性能
* 3)TreeSet:
* 1.底层结构里面维护了一个TreeMap都是基于红黑树实现的
* 2.特点不允许重复实现排序(自然排序或定制排序)
* 如何实现去重:如果使用的是自然排序则通过调用实现的compareTo方法;如果使用的是定制排序则通过调用比较器的compare方法
* 如何实现排序:
* 方式一自然排序:让待添加的元素类型实现Comparable接口并重写compareTo方法
* 方式二定制排序:创建Set对象时指定Comparator比较器接口并实现compare方法
* @Version: 1.0
*/
public class SetTest {
//测试将重写了hashcode和equal方法的类放入HashSet中
@Test
public void test() {
HashSet<Employee> set = new HashSet<>();
set.add(new Employee("张三", new Employee.MyDate(1990, 1, 1)));
//重复元素无法添加因为MyDate和Employee重写了hashCode和equals方法
set.add(new Employee("张三", new Employee.MyDate(1990, 1, 1)));
set.add(new Employee("李四", new Employee.MyDate(1992, 2, 2)));
for (Employee object : set) {
System.out.println(object);
}
}
//测试LinkedHashSet
@Test
public void test1() {
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("张三");
set.add("李四");
set.add("王五");
set.add("张三");
System.out.println("元素个数:" + set.size()); //3
for (String name : set) {
System.out.println(name); //张三 李四 王五
}
}
//测试TreeSet的自然排序
@Test
public void test2() {
TreeSet<String> set = new TreeSet<>();
set.add("zhangsan"); //String它实现了java.lang.Comparable接口
set.add("zisi");
set.add("wangwu");
set.add("hangsan");
System.out.println("元素个数:" + set.size());
for (String str : set) {
System.out.println(str);
}
}
//测试TreeSet的定制排序
@Test
public void test3() {
TreeSet<Student> set = new TreeSet(new Comparator<Student>(){
@Override
public int compare(Student o1, Student o2) {
return o1.getId() - o2.getId();
}
});
set.add(new Student(3,"张三"));
set.add(new Student(1,"李四"));
set.add(new Student(2,"王五"));
set.add(new Student(3,"张三风"));
System.out.println("元素个数:" + set.size()); //3
for (Student stu : set) {
System.out.println(stu); //Student [id=1, name=李四];Student [id=2, name=王五];Student [id=3, name=张三]
}
}
}
class Employee {
private String name;
private MyDate birthday;
public Employee(String name, MyDate birthday) {
super();
this.name = name;
this.birthday = birthday;
}
public Employee() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((birthday == null) ? 0 : birthday.hashCode());
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;
Employee other = (Employee) obj;
if (birthday == null) {
if (other.birthday != null)
return false;
} else if (!birthday.equals(other.birthday))
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 + ", 生日:" + birthday;
}
static class MyDate {
private int year;
private int month;
private int day;
public MyDate(int year, int month, int day) {
super();
this.year = year;
this.month = month;
this.day = day;
}
public MyDate() {
super();
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + day;
result = prime * result + month;
result = prime * result + year;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyDate other = (MyDate) obj;
if (day != other.day)
return false;
if (month != other.month)
return false;
if (year != other.year)
return false;
return true;
}
@Override
public String toString() {
return year + "-" + month + "-" + day;
}
}
}
class Student{
private int id;
private String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//......这里省略了name属性的get/set
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}