集合体系:
Collection:单列集合,每个元素只代表一个值
注:Collection<E>是接口,同时拥有很多子接口,例List<E>,Set<E>接口
List<E>下面实现类(Arrylist<E>,LinkedList<E>等)
Set<E>下面实现类(TreeSet<E>,HashSet<E>(子类LinkedHashSet)等)
List系列集合:添加的元素是有序,可重复,有索引。
Arrylist<E>,LinkedList<E>:有序,可重复,有索引
Set系列集合:添加的元素是无序,不重复,无索引。
HashSet<E>:无序,不重复,无索引
LinkedHashSet:有序,不重复,无索引
TreeSet<E>:按照大小默认升序排序,不重复,无索引
注:集合中存储的是对象地址
Collection常用方法
public bollean add(E e) | 添加元素,成功返回true |
public void clear() | 清空集合中的元素 |
public bollean isEmpty | 判断集合是否为空,空返回true |
public int size | 获取集合大小 |
public bollean contains(objjrc) | 判断集合中是否包含某个元素 |
public bollean remove (E e) | 删除元素,如果有多个元素默认删除第一个出现的 |
public Object[] toArray() | 把集合转为数组 |
Collection<String> a1 = new ArrayList<>();
//添加元素,成功返回true
a1.add("aa");
a1.add("bb");
a1.add("cc");
a1.add("bb");
//清空集合中的元素
// a1.clear();
System.out.println(a1);
//判断集合是否为空,空返回true
System.out.println(a1.isEmpty());
//判断集合中是否包含某个元素
System.out.println(a1.contains("aa"));
//获取集合大小
System.out.println(a1.size());
//删除元素,如果有多个元素默认删除第一个出现的
a1.remove("bb");
System.out.println(a1);
//把集合转为数组
Object[]arr=a1.toArray();
String[] b= a1.toArray(new String [a1.size()]);//此数组类型数据只能是String
Collection<String> a12= new ArrayList<>();
a12.add("ccc");
a12.add("ccc");
a12.add("ccc");
//将a12数据存储到a1;
a1.addAll(a12);
System.out.println(a1);
迭代器:用于遍历集合的专用方式,例Iterator
注:数组没有迭代器
Collection集合获取迭代器的方法
方法名称 | 说明 |
Interator<E> iterator() | 返回集合中的迭代对象,该迭代器对象默认指向集合第一个元素 |
Iterator迭代器中的常用方式
方法名称 | 说明 |
boolean hasNext() | 询问当前位置是否有元素存在,存在返回true |
E next | 获取当前位置的元素,并同时将迭代器对象指向下一个元素处 |
Collection<String> a=new ArrayList<>();
a.add("姓名");
a.add("班级");
a.add("年龄");
a.add("身高");
a.add("姓名");
a.add("体重");
Iterator<String> it = a.iterator();//alt+enter可以补全代码
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
// System.out.println(it.next());多余数组长度会出异常
while (it.hasNext()) {
String e= it.next();
System.out.println(e);
}
增强for循环
可以用于遍历数组或集合
注:增强for遍历数组,本质上就是迭代器遍历集合的简化写法
格式:
for(元素的数据类型 变量名:数组或者集合名称){
}
Collection<String> b=new ArrayList<>();
b.add("姓名");
b.add("班级");
b.add("年龄");
b.add("身高");
b.add("姓名");
int arr[]={1,2,3,4};
//快捷键数组名或集合名加.for
for (String s : b) {
System.out.println(s);
}
for (int i : arr) {
System.out.println(i);
Lambda表达式遍历集合
方法名称 | 说明 |
default void forEach (Consumer<?super T> action | 结合Lambda遍历集合 |
Collection<String> a=new ArrayList<>();
a.add("星期一");
a.add("星期二");
a.add("星期三");
a.add("星期四");
a.add("星期五");
System.out.println(a);
// a.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });
// a.forEach((String s)-> {
// System.out.println(s);
// });
// a.forEach( s-> System.out.println(s));
a.forEach( System.out::println);
List
public void add(int index,E element) | 在某个索引位置插入元素 |
public E remove(int index) | 根据索引删除元素,返回被删除的元素 |
public E get (int index | 返回集合中指定位置的元素 |
public E set(int index,E element) | 修改索引位置处的元素,修改成功后返回原来的数据 |
list还可以使用for循环遍历
for (int i = 0; i < b.size(); i++) {
System.out.println(b.get(i));
ArrayList集合底层原理(基于数组实现)
查询快,增删慢
利用无参构造器构造的集合,会在底层创建一个默认长度为0的数组,
当开始添加数据,会创建新的长度为10的数组,当长度为10的数组存
满,会扩容到15,再装满,新建数组长度为实际长度。
linkedList集合底层原理(基于双链表实现)
特点:查询慢,增删快,但对于首尾元素增删改查快
public void addFirst(E e) | 在列表开头插入指定元素 |
public void addLast(E e) | 将指定元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
两者适用场景
ArrayList:适合根据索引查数据,或者数据量不大
不适合数据大,且需要频繁的增删的场景
LinkedList:
1.可以用于设计队列(先进先出,后进后出)
LinkedList<String> queue=new LinkedList<>();
queue.addLast("1");
queue.addLast("2");
queue.addLast("3");
queue.addLast("4");
//queue.add("1"); 与这样加一样
for (int i = queue.size()-1; i >=0; i--) {
System.out.println(queue.removeFirst());
}
2.用于设计栈(先进后出,后进先出)
LinkedList<String> stack=new LinkedList<>();
stack.addFirst("1");
stack.addFirst("2");
stack.addFirst("3");
stack.addFirst("4");
for (int i = stack.size()-1; i >=0; i--) {
System.out.println(stack.removeFirst());
}
HashSet:基于哈希表实现
哈希表=数组+链表+红黑树
HashSet是一种增删改查数据,性能都较好的数据结构(使用hashCode取哈希值)
注:两个内容一样的学生对象存入HashSet集合中去,HashSet不能去重复(因为不同对象的哈希值不一样),要是想去重复,需要重写hashCode和euqals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Students students = (Students) o;
return age == students.age && Double.compare(students.height, height) == 0 && Objects.equals(name, students.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, height);
}
LinkedHashSet:有序,不重复,无索引
也基于哈希表,但比hashSet多一个双链表
TreeSet:可排序序,不重复,无索引
对于数值型按数字大小排序
对于字符串型,按照首字符的编号排序
对于自定义类型如Student对象,无法直接排序
因此自定义比较规则
法一:让自定义的类实现Comparable接口,重写里面的comparableTo
方法来指定比较规则
class Students implements Comparable<Students>{
@Override
public int compareTo(Students o) {
return this.age-o.age;
}
法二:通过调用TreeSet集合有参构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)
Set<Students> k=new TreeSet<>(( o1, o2)->o1.getAge()-o2.getAge());
简化的并发修改异常:使用迭代器遍历集合时,又同时删除数据,出现的错误
增强for循环出现这种情况无法解决
Iterator可以解决
Iterator<String>it=li.listIterator();
while (it.hasNext()) {
String name = it.next();
if (name.contains("李")) {
it.remove();//自己的方法
}
}
或者使用for循环解决
for (int i = 0; i < li.size(); i++) {
String name1 = li.get(i);
if (name1.contains("李")) {
li.remove(name1);
i--;//
}
}
Collection其他知识:
可变参数:一种特殊形参,定义在方法、构造器的形参列表里,
格式是:数据类型..参数名称;
public static void b(int...b) {
System.out.println(2);
}
可变参数的特点和好处
特点:可以不传数据给它;可以传-一个或者同时传多个数据给它;也可以传一 个数组给它。
好处:常常用来灵活的接收数据。
public static void main(String[] args) {
b();
a(10);
a(10,20,30);
a(1,new int []{10,20,30});
}
public static void b(int...b) {
System.out.println(2);
}
public static void a(int a,int...b){
System.out.println(b.length);
System.out.println(Arrays.toString(b));
}
可变参数的注意事项:
可变参数在方法内部就是一个数组;
一个形参列表中可变参数只能有一个;
可变参数必须放在形参列表的最后面
collections:一个用来操作集合的工具类
方法名称 | 说明 |
public static <T> boolean addAll(Collection<? super T> C, T... elements) | 给集合批量添加元素 |
public static void shuffle(List<?> list) | 打乱List集合中的元素顺序 |
public static <T> void sort(List<T> list) | 对List集合中的元素进行升序排序 |
public static <T> void sort(List<T> list, Comparatorc? super T> c) | 对List集合中元素,按照比较器对象指定的规则进行排序 |
public class first {
public static void main(String[] args) {
// public static <T> boolean addAll(Collection<? super T> C, T... elements)给集合批量添加元素
List<String> a=new ArrayList<>();
Collections.addAll(a,"1","4","6");
System.out.println(a);
// public static void shuffle(List<?> list)打乱List集合中的元素顺序
Collections.shuffle(a);
System.out.println(a);
// public static <T> void sort(List<T> list) 对List集合中的元素进行升序排序
List<Integer>b=new ArrayList<>();//!!!!需要是List而不是其他
b.add(1);
b.add(3);
b.add(4);
b.add(9);
b.add(1);
Collections.sort(b);
System.out.println(b);
List<Movies> movie=new ArrayList<>();
movie.add(new Movies("绿皮书",9.2,"a"));
movie.add(new Movies("阿甘正传",8.6,"a"));
movie.add(new Movies("肖申克的救赎",8.9,"c"));
Collections.sort(movie,(o1,o2)->Double.compare(o1.getScore(),o2.getScore()));
//是o1.getScore(),o2.getScore()
System.out.println(movie);
// public static <T> void sort(List<T> list, Comparatorc? super T> c)对List集合中元素,按照比较器对象指定的规则进行排序
}
}
class Movies implements Comparable<Movies>{//<Movies>要有
private String name;
private double score;
private String actor;
@Override
public int compareTo(Movies o) {
// return Double.compare(this.Score-o.Score);错误写法
return Double.compare(this.score,o.score);
}
场景选择
1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
用ArrayList集合 (有序、可重复、有索引) ,底层基于数组的。 (常用 )
2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?
用LinkedList集合 (有序、可重复、有索引),底层基于双链表实现的。
3.如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
用HashSet集合 (无序,不重复,无索引),底层基于哈希表实现的。( 常用)
4.如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
用LinkedHashSet集合 (有序,不重复,无索引),底层基 于哈希表和双链表。
5.如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
用TreeSet集合, 基于红黑树实现。
Map:双列集合,每个元素包含两个值(键值对)
Map系列集合的特点都是由键决定,值只是一个附属品,值不做要求
HashMap<E>(由键决定特点):无序,不重复,无索引(用的最多)
LinkedHashMap(由键决定特点):有序,不重复,无索引
TreeMap<E>(由键决定特点):按照大小默认升序排序,不重复,无索引
Map<String,Integer> a=new HashMap<>();//无序,不重复,相同后者覆盖前者,无索引
Map<String,Integer>a=new LinkedHashMap<>();//有序,不重复,相同后者覆盖前者,无索引
a.put("a",11);
a.put("d",12);
a.put("ac",16);
a.put("a",15);
a.put(null,null);
//TreeMap排序依照第一个变量
Map<String,Integer> c=new TreeMap<>();//可排序,不重复,相同后者覆盖前者,无索引
c.put("a",11);
c.put("d",12);
c.put("ac",16);
c.put("a",15);
// c.put(null,null);不可以有
System.out.println(c);//a=15, ac=16, d=12
Map<Integer,String> c1=new TreeMap<>();
c1.put(16,"a");
c1.put(17,"ac");
c1.put(16,"c");
c1.put(18,"d");
System.out.println(c1);//16=c, 17=ac, 18=d
Map的常用方法
方法名称 | 说明 |
public V put(K key,V value) | 添加元素 |
public int size() | 获取集合的大小 |
public void clear( ) | 清空集合 |
public boolean isEmpty() | 判断集合是否为空,为空返回true,反之 |
public V get(Object key) | 根据键获取对应值 |
public V remove(Object key) | 根据键删除整个元素 |
public boolean containsKey(Object key) | 判断是否包含某个键 |
public boolean containsValue(Object value) | 判断是否包含某个值 |
public Set<K> keySet( ) | 获取全部键的集合 |
public Collection<V> values( ) | 获取Map集合的全部值 |
public static void main(String[] args) {
// public V put(K key,V value)添加元素
Map<String,Integer> a = new HashMap<>();
a.put("a",11);
a.put("d",12);
a.put("ac",16);
a.put("a",15);
a.put(null,null);
// public int size() 获取集合的大小
System.out.println(a.size());
// public void clear( ) 清空集合
// a.clear();
// public boolean isEmpty() 判断集合是否为空,为空返回true,反之
System.out.println(a.isEmpty());
// public V get(Object key)根据键获取对应值
int k=a.get("a");
System.out.println(k);//15
System.out.println(a.get(""));//返回null,没有则返回null
// public V remove(Object key)根据键删除整个元素
a.remove("d");
System.out.println(a);
// public boolean containsKey(Object key)判断是否包含某个键返回false或true
System.out.println(a.containsKey("a"));//true
// public boolean containsValue(Object value) 判断是否包含某个值返回false或true
System.out.println(a.containsValue(11));
// public Set<K> keySet( ) 获取全部键的集合
Set<String> aaaaa=a.keySet();
System.out.println(aaaaa);
// public Collection<V> values( ) 获取Map集合的全部值
Collection<Integer> bbbbbb=a.values();
System.out.println(bbbbbb);
// 把其他Map集合数据导入自己集合
Map<Integer,String> a1=new LinkedHashMap<>();
a1.put(11,"c");
a1.put(12,"b");
a1.put(16,"b");
a1.put(11,"a");
a1.put(null,null);
Map<Integer,String> c1=new TreeMap<>();
c1.put(16,"a");
c1.put(17,"ac");
c1.put(16,"c");
c1.put(18,"d");
a1.putAll(c1);
System.out.println(a1);
//
Map集合的遍历方式
problems集合
使用前看是否有import java.util.Collection;
无则alt+enter
Collection<String> a1 = new ArrayList<>();
2.
List<String> queue=new LinkedList<>();//这样不能使用LinkedList的方法removeFirst()
LinkedList<String> queue=new LinkedList<>();//这样才可以
3.使用for循环删除数组时注意:如果for循环的判断条件是
数组名.size()时需要注意,因为删除了数组中的数据,所以
数组长度也会变化,可以将原先数组长度1用一个数表示出来,
或者倒着删除
//法一:
int a= queue.size() ;
for (int i = 0; i < a; i++) {
System.out.println(queue.removeFirst());
//法二:
for (int i = queue.size()-1; i >=0; i--) {
System.out.println(queue.removeFirst());
}//切记倒着遍历时不要忘了改成i-- ;