目录:
集合(List)
和数组一样对多个数据进行存储。
Map用来存储一对一对(key-value)的数据,类似高中的函数y=f(x),
Collection API测试
数组和集合之间的相互转换
数组到集合:Arrays.asList(T ... t)
集合到数组:toArray()
package com.lzy.collectionlearn;
import java.util.Objects;
/**
* @author: lzy
* @description: Person类
* @date: 2020-09-14-15:01
*/
public class Person {
private String name;
private int age;
Person(){}
public Person(String name, int age){
name=name;
age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
package com.lzy.collectionlearn;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @author: lzy
* @description: 用来测试Collection中接口的方法
* @date: 2020-09-14-11:10
*/
public class CollectionTest {
@Test
public void test1(){
Collection coll=new ArrayList();//这个地方就是多态
//添加元素e到集合中
coll.add("aa");
coll.add(123);//自动装箱
//获取元素个数
System.out.println(coll.size());
//addAll()
Collection coll1=new ArrayList();
coll1.add("bb");
coll1.add("cc");
coll.addAll(coll1);
System.out.println(coll.isEmpty());
coll1.clear();
coll.add(new String("Tom"));
coll.add(new Person("ni",20));//可以放入自定义类
boolean contains1=coll.contains(123);
System.out.println(contains1);
System.out.println(coll.contains(new String("Tom")));//true
System.out.println(coll.contains(new Person("ni",20)));//false,如果重写equals方法就可以成为true,如果不重写就是Object的equals()
//containsAll(Collection coll2)判断是否coll1都在coll中
Collection coll2= Arrays.asList(123,4567);
System.out.println(coll.containsAll(coll2));
coll.remove(123);
//删除coll1中的coll2的所有元素。
coll1.removeAll(coll2);
//获取交集。
coll1.retainAll(coll2);
//完全相同返回true,包括顺序也要相同。
coll.equals(coll2);
//hashCode()返回当前对象的哈希值
System.out.println(coll.hashCode());
//集合-->数组
Object[] arr=coll.toArray();
for (int i=0;i<arr.length;i++)
{
System.out.println(arr[i]);
}
//数组-->集合
List<String> strings = Arrays.asList(new String[]{"aa", "bb", "cc"});
System.out.println(strings);
List arr1=Arrays.asList(new int[]{123,456});
System.out.println(arr1.size());//1,通过下面的输出可以看出,系统把整个arr1当做了一个整体,而不是单独的两个
System.out.println("==============================");
System.out.println(arr1);// [[I@4f2410ac]
List arr2=Arrays.asList(new Integer[]{123,456});
System.out.println(arr2.size());//2
System.out.println(arr2);// [123, 456]
//iterator迭代器接口,用于集合元素的遍历
}
}
需要注意的是:在下图第二种方法中如果 new一个int类型的数组是没法存入数组中的属性的,只能把这个数组作为衣蛾整体存入到集合中。需要转换成Integer包装类才行。
第二:正常来说我们直接加Arrays.asList({..........})即可,这样可以避免数据的类型·错误。
Iterator
一般来说使用iterator.hasNext()函数来判断是否遍历完成。
错误举例:
错误方式1会造成跳着输出,并且最后会导致抛出异常
错误方式2会造成一直输出第一个。无限循环。
iterator.remove()移除某一个数据。
但是在删除了一个数据之后不能再删除一次,需要next才能再删除。
package com.lzy.collectionlearn;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author: lzy
* @description: Iterator联系
* @date: 2020-09-14-15:43
*/
public class IteratorTest {
@Test
public void test1(){
Collection coll=new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry",11));
coll.add(new String("nihao"));
coll.add(false);
Iterator iterator = coll.iterator();
System.out.println(iterator);//指向的是这个集合的地址
System.out.println(iterator.next());//第一个元素
while(iterator.hasNext())// 常用的方法,用来遍历,遍历前判断了是否还要下一个值
{
System.out.println(iterator.next());
}
}
}
foreach(内部使用的是迭代器)
可以遍历集合和数组。
注意如果修改obj,是不会改变本身的集合元素。改变的是局部变量。
ArrayList,LinkedList,Vector异同
同:都是作为List接口的实现类,都是有序的可重复的数据。
不同:ArrayList:作为List接口的主要实现类,线程不安全的的,效率高,底层使用数组实现
Vector:作为List接口的古老实现类,线程安全的,效率低。使用数组实现
LinkedList:底层使用双向链表存储。
jdk8.0中(7类似饿汉式。8类似懒汉式,延迟了数组创建)
在定义了实例后底层并没创建一个有长度的数组,只有在第一次add之后才真正创建一个有长度的数组,后续的添加和扩容中的操作和jdk7无异。
List接口的常用方法:
set接口
set中没有新定义的方法,不像list中有索引需要自定义犯法。
set底层实现同样是使用的数组方式。
set的无序性:并非是随机性的,存储的数据在底层的数组中不是按照从头到尾的顺序进行添加,而是按照哈希算法添加。
set的不可重复性:添加的元素按照equals()方法判断时,不能返回true。即:相同的元素只能添加一个。
set添加元素过程:(HashSet为例)
JDK7,把原来的元素放到链表上,JDK8把新加的元素放到链表上。
要求:1。向set中添加数据,其所在的类一定要重写hashCode(),equals()方法,并且重写的两个方法要保持一致性。(用来保证:相等的对象具有相等的散列码)
LinkedHashSet
作为HashSet的子类,添加方法在原来的基础上增加了头尾指针,实现了按照添加顺序顺序遍历的功能,但是本身在底层存放的是无序的(按照上HashSet),对于频繁的便利操作,效率更高。
TreeSet(底层为红黑树)
向TreeSet中添加的数据,要求是相同类的对象,不可以添加不同类的对象。(例如只能添加Integer类型或者Boolean或者自定义类)
在TreeSet中比较本身就是使用的compareTo方法比较。所以当比较结果是0就会当做相同。不再是上面方法的equals()。
并且自动排序按照从小到大顺序排列。
但是自定义类中需要重写排序方法也就是之前讲过的(comparable和compareTo,位于章节比较器)
自然排序举例(代码在最后):
定制排序举例:
例2:
如果不添加参数也就是com,会按照默认方式进行排序,如果添加参数就会按照参数方式进行排序。(注意按照上述代码方式进行排序,如果出现相同的年龄时,会出现其他相同的年龄内容消失,因为只比较年龄导致了compareTo方式比较结果为0.这个时候就会出现系统认为两者相同的情况,即使name不相同也不会判断为不相同对象。如果要修复这个问题需要修改比较方式。)
set,TreeSet案例代码:(已经放入github->这个)
文件结构如下:
以上文件代码如下所示:
Employee:
package com.lzy.setlearn;
/**
* @author: lzy
* @description:
* @date: 2020-09-16-14:27
*/
public class Employee implements Comparable{
private String name;
private int age;
private MyDate birthday;
public Employee(){}
public Employee(String name, int age, MyDate birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public MyDate getBirthday() {
return birthday;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
@Override
public int compareTo(Object o) {
if (o instanceof Employee){
Employee e=(Employee)o;
return this.name.compareTo(e.name);
}
else{
throw new RuntimeException("error");
}
}
}
MyDate:
package com.lzy.setlearn;
/**
* @author: lzy
* @description:
* @date: 2020-09-16-14:26
*/
public class MyDate {
private int year;
private int month;
private int day;
public MyDate() {
}
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public void setYear(int year) {
this.year = year;
}
public void setMonth(int month) {
this.month = month;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
SetLearn:
package com.lzy.setlearn;
import com.lzy.collectionlearn.Person;
import org.junit.Test;
import java.util.HashSet;
import java.util.Iterator;
/**
* @author: lzy
* @description: 联系set接口
*
* @date: 2020-09-16-10:44
*/
public class SetLearn {
@Test
public void test1(){
HashSet set = new HashSet();
set.add(123);
set.add(456);
set.add("aa");
set.add("cc");
set.add(new Person("Tom",12));
Iterator iter=set.iterator();
while (iter.hasNext()){
System.out.println(iter.next());
}
}
}
TreeSetTest:
package com.lzy.setlearn;
import org.junit.Test;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @author: lzy
* @description: 写一个TreeSet例题
* @date: 2020-09-16-14:31
*/
public class TreeSetTest {
//使用自然排序,使Employee实现全Comparable接口,并且按照name排序
@Test
public void test1(){
TreeSet set =new TreeSet();
Employee e1=new Employee("name1",1,new MyDate(1990,1,1));
Employee e2=new Employee("name4",4,new MyDate(1923,3,23));
Employee e3=new Employee("name3",3,new MyDate(1978,6,12));
Employee e4=new Employee("name4",8,new MyDate(1998,3,18));
Employee e5=new Employee("name5",23,new MyDate(1999,3,31));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
//System.out.println(set);
Iterator iterable=set.iterator();
while(iterable.hasNext())
System.out.println(iterable.next());
}
//定制排序,按照生日顺序进行排序
@Test
public void test2(){
TreeSet set =new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Employee && o2 instanceof Employee){
Employee e1=(Employee)o1;
Employee e2=(Employee)o2;
MyDate b1=e1.getBirthday();
MyDate b2=e2.getBirthday();
int sumYear=b1.getYear()-b2.getYear();
int sumMonth=b1.getMonth()-b2.getMonth();
System.out.println("*******");
if(sumYear!=0)
return sumYear;//是通过差值进行比较
if(sumMonth!=0)
return sumMonth;
return b1.getDay()-b2.getDay();
}
throw new RuntimeException("error1");
}
});
Employee e1=new Employee("name1",1,new MyDate(1990,1,1));
Employee e2=new Employee("name4",4,new MyDate(1923,3,23));
Employee e3=new Employee("name3",3,new MyDate(1978,6,12));
Employee e4=new Employee("name4",8,new MyDate(1998,3,18));
Employee e5=new Employee("name5",23,new MyDate(1999,3,31));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
Iterator iterable=set.iterator();
while(iterable.hasNext())
System.out.println(iterable.next());
}
}