首先,集合只能存储引用类型的对象。
集合 和 数组区别:
1.数组 长度固定的;
集合 长度不固定;
2.数组 存储 基本 类型 和 引用类型;
集合 只能存储引用类型;
3.性能上。
数组更好;
集合底层数据结构复杂。
这篇文章先只说左边部分 也就是 Collection接口的List 和 Set。
上边的接口图如果觉得看的不爽,可以瞧瞧这里https://www.cnblogs.com/ysocean/p/6555373.html
Collection接口:
存储数据可以重复并且是无序的。
Collection下 List 接口实现了 存储的数据可以重复,但是有序的
Set 接口则实现了存储数据的无序,但是唯一
先说List 的实现类 ArrayList:
下面看关系:
public interface List<E> extends Collection<E>
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
public class ArrayList<E> extends AbstractList<E>
所有的集合都是这样的,Collection->List->抽象类->ArrayList(实现类)
写一个Demo吧,看一下ArrayList能用的方法。
package day0815;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
public class Demo1 {
public static void main(String[] args) {
//创建集合
//这里为什么要这样写呢,当然你写ArrayList list=new ArrayList();
//也是没关系的,说不上来为什么,可能就属于编程习惯?! 体现了多态嘛
Collection<String> c=new ArrayList();
//集合是否为空 空的话返回为true
System.out.println(c.isEmpty());
//为集合添加元素
c.add("1");
c.add("3");
c.add("2");
//增强for循环,只能对有序的,这点有序指的是有下标的,对于Set则不能用for循环遍历
for(String a:c) {
System.out.println(a);
}
System.out.println(c);
//打印集合的长度 数组是,length 集合是size()
System.out.println(c.size());
//addAll()方法是向集合添加整个集合,如下 把c 加到c 里
c.addAll(c);
c.addAll(c);
c.addAll(c);
//再看看大小
c.size();
//移除 集合 c 中的 d元素,返回值为boolean ,有这个元素删除了 返回true,没有则返回 false
System.out.println(c.remove("d"));
//在集合中删除传入集合所有元素,只要删除了一个则返回true,否则返回false(重复的元素也会删除)
// c.removeAll(c);
System.out.println(c);
//符合条件的删除,匿名内部类重写方式
c.removeIf(new Predicate<String>() {
@Override
public boolean test(String t) {
// TODO Auto-generated method stub
if(Integer.valueOf(t)>1) {
return true;
}else {
return false;
}
}
});
//Lambda表达式定义范围
c.removeIf(s->s.length()>1);
//判断集合中是否存在元素
System.out.println(c.contains("1"));
//判断集合是否是另一个集合的子集是的话返回true,否则false
System.out.println(c.containsAll(c));
//把数组转换成集合 但是这个集合不是ArrayList,不能添加,删除,一般只是遍历用
List<String> list=Arrays.asList(new String[]{"",""});
System.out.println(c);
//把集合转为数组
Object []all=c.toArray();
String [] wtf=c.toArray(new String [c.size()]);
for(Object a:wtf) {
System.out.println(a);
}
c.clear();
}
}
package day0815;
import java.util.ArrayList;
import java.util.List;
public class Demo2 {
public static void main(String[] args) {
List <String> list=new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
System.out.println(list);
list.add(1, "ff");
//修改下标为2的元素改为 “wtf”
list.set(2, "wtf");
System.out.println(list);
//取得下标为0的元素
System.out.println(list.get(0));
//是否存在“aa”元素,存在返回true 否则返回false
System.out.println(list.indexOf("aa"));
//返回最后一个“aa”的元素的开始的下标
System.out.println(list.lastIndexOf("aa"));
//集合截取 类比SubString
System.out.println(list.subList(0, 2));
//排序,传入空类型实现默认自然排序
list.sort(null);
System.out.println(list);
}
}
package day0815;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
public class Demo3 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
// //1.基本for循环只限于List
// for(int i=0;i<list.size();i++) {
// System.out.println(list.get(i));
// }
// //2.增强for
// for(String s:list) {
// System.out.println(s);
// }
// //3.集合的方法
// list.forEach(new Consumer<String>() {
//
// @Override
// public void accept(String t) {
// // TODO Auto-generated method stub
// System.out.println(t);
// }
//
// });
//Lambda 简化
// list.forEach(t->System.out.println(t));
// list.forEach(System.out::println);
//属于集合的Iterator 迭代器
Iterator<String> it=list.iterator();
System.out.println(it.next());
// while(it.hasNext()) {
// System.out.println(it.next());
// list.add("hello");
// }
ListIterator<String> li=list.listIterator();
while(li.hasNext()) {
System.out.println(li.next());
li.add("Hello");
}
// while(li.hasPrevious()) {
// System.out.println(li.previous());
// li.add("Hello");
// }
System.out.println(list);
//it 是个类似指针 不会返回
// it.forEachRemaining(System.out::println);
list.stream().forEach(System.out::println);
}
}
工具类Collections:
package day0816;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
//工具类
Collections.addAll(list, "aa","bb","cc");
System.out.println(list);
//默认自然升序排序
Collections.sort(list);
System.out.println(list);
//指定比较器
// Collections.sort(list, (o1,o2)->o2.compareTo(o1));
// System.out.println(list);
//二分查找元素没有的话返回-1 有的话 返回下标 前提是升序排序的
System.out.println(Collections.binarySearch(list, "aa"));
//最小元素
System.out.println(Collections.min(list));
//最大元素
System.out.println(Collections.max(list));
//在集合中出现的次数
System.out.println(Collections.frequency(list, "aa"));
//反转集合
Collections.reverse(list);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
//洗排 每次都不一样
Collections.shuffle(list);
System.out.println(list);
//以什么填充、全部替换
Collections.fill(list, "wtf");
System.out.println(list);
}
}
package day0816;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("李四");
list.add("王五");
list.add("张三");
Set<String> set=new HashSet<>(list);
for(String t:set) {
//是否 有重复的元素 是返回true 否则 false
if(Collections.frequency(list,t)!=1) {
System.out.println(t+"重复");
}
}
}
}
List 的实现类还有 Vector 通过栈实现的 ,已废弃。LinkedList 呢 其实方法实现和 ArrayList差不太多,因为底层实现的原因,多了在头部和尾部插入。
总结一下:
ArrayList :按照 50 %扩容
底层数据结构 是数组:
遍历 和 随机访问效率高。
Vector -> Stack栈
按照 100%扩容
性能低.
线程安全的。
底层数据结构 是链表。
LinkedList
插入 和 删除 效率高。
下面说Set 接口
Set接口实现了数据唯一存储,但是无序
HashSet:
和ArrayList一样的
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>
public class HashSet<E> extends AbstractSet<E>implements Set<E>
都是 接口->抽象类->实现类
HashSet 类:
底层数据结构是 哈希表
下面上Demo,用法其实毕竟同源(都来自Collection接口)都差不多的
package day0815;
import java.util.HashSet;
import java.util.Set;
class Empoloyee{
int no;
String name;
public Empoloyee(int no, String name) {
super();
this.no = no;
this.name = name;
}
}
public class Demo7 {
public static void main(String[] args) {
//定义一个set集合
Set<Empoloyee> set=new HashSet<>();
Empoloyee zhangsan=new Empoloyee(1, "zhangsan");
Empoloyee lsi=new Empoloyee(3, "lsi");
Empoloyee ww=new Empoloyee(2, "ww");
//往里存,如果你再存相同对象的你会发现存不进去的,当然了 new 一个新的另说的
set.add(lsi);
set.add(ww);
set.add(zhangsan);
}
}
TreeSet:
底层数据结构 二叉树
树: 层次结构.
package day0815;
import java.util.SortedSet;
import java.util.TreeSet;
public class Demo9 {
public static void main(String[] args) {
//没有索引 //这里是重写了排序方法
SortedSet<Integer> set=new TreeSet<>((n1,n2)->n2-n1);
set.add(1);
set.add(3);
set.add(2);
System.out.println(set);
System.out.println(set.first());
System.out.println(set.last());
//【起始元素,终止元素)***
//如果改变排序方式的话,这点就会出问题
// System.out.println(set.subSet(2,1);
}
}
package day0815;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.TreeSet;
public class Demo10 {
public static void main(String[] args) {
//这个我觉得就是增强的迭代器
NavigableSet<Double> set=new TreeSet<>();
set.add(11.1);
set.add(22.3);
set.add(44.4);
set.add(111.1);
//小于等于指定参数的最大元素
System.out.println(set.floor(23.0));
//大于等于指定参数的最小元素
System.out.println(set.ceiling(20.2));
//降序的集合
System.out.println(set.descendingSet());
//降序的迭代器
set.descendingIterator().forEachRemaining(System.out::println);
//把第一个元素删除
set.pollFirst();
System.out.println(set);
//把在最后一个的元素删除
System.out.println(set.pollLast());
}
}
下面才是最重要的,自定义HashSet的排序方法 、
Hash唯一存储原理:
首先 调用 hashCode()算出一个 哈希地址 ,
把 元素 存进去 ,如果 ,哈希 冲突的 ,
hashCode()的值 一样了 ,这时 才会调用‘
equals()判断 两个对象是否相同 ,相同不存储,
不同 可以存储。’
package work0815;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Mouse implements Comparable{
String name;
String favorite;
int age;
@Override
//自定义hashCode的方法,让算hashCode 是通过this.name.hashCode()+this.age 去计算
public int hashCode() {
// TODO Auto-generated method stub
return this.name.hashCode()+this.age;
}
@Override
//自定义判断大小的方法
public boolean equals(Object obj) {
// TODO Auto-generated method stub
Mouse mouse=null;
if(obj instanceof Mouse) {
mouse=(Mouse)obj;
}
return this.name.equals(mouse.name);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.age+"";
}
public Mouse(String name, String favorite, int age) {
super();
this.name = name;
this.favorite = favorite;
this.age = age;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return this.age-((Mouse)o).age;
}
}
public class Work2 {
public static void main(String[] args) {
Mouse m1=new Mouse("qwe", "看书", 2);
Mouse m2=new Mouse("asd", "看报", 4);
Mouse m3=new Mouse("zcx", "学习", 1);
Set<Mouse> set=new HashSet<>();
set.add(m1);
set.add(m2);
set.add(m3);
//转为List 集合 进行排序
List<Mouse> list=new ArrayList<>(set);
list.sort(null);
System.out.println(list);
System.out.println(set);
Mouse m4=new Mouse("qwe", "2", 2);
set.add(m4);
System.out.println(set);
//这样的话 即使是新对象也是存不进去的
set.remove(new Mouse("qwe", "睡觉", 2));
System.out.println(set);
}
}