这可能是你见过最全的集合
作者:互联网
Collection集合特点
- List系列集合:添加的元素是有序的,可重复,有索引的。
- ArrayList、LinekdList:有序,可重复,有索引
- Set系列集合:添加的元素是无序,不重复,无索引。
- HashSet:无序、不重复==、无索引;
- LinkedHashSet:有序、不重复、无索引。
- TreeSet:按照大小默认升序排序,不重复,无索引
注意:集合和泛型都只能支持引用数据类型,不支持基本数据类型,所以集合中存储的元素都认为是对象
Collection API
package com.djn.day1;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionApi {
public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();
list.add("java");
list.add("java");
list.add("mysql");
list.add("html");
list.add("css");
System.out.println("list.add的返回值boolean:"+list.add("css")); //返回值为true;
System.out.println("判断字符是否为空---->"+list.isEmpty());
System.out.println("获取集合的长度---->"+list.size());
System.out.println("判断集合是否包含某个元素:---->"+list.contains("java"));
System.out.println("从集合中删除一个元素:---->"+list.remove("java"));
//将集合转换成数组,
Object[] arrs = list.toArray();
System.out.println("数组---->"+Arrays.toString(arrs));
System.out.println("----------------拓展-----------------");
Collection<String> c1 = new ArrayList<String>();
c1.add("陈奕迅");
c1.add("韩红");
Collection<String> c2 = new ArrayList<String>();
c2.add("呵呵");
c2.add("哈哈");
//addAll把c2中的集合全部复制c1中去 ,
c1.addAll(c2);
System.out.println(c1);
System.out.println(c2);
}
}
Collection遍历方式
Iterator迭代器遍历collection集合
boolean hashNext():获取当前位置是否有元素存在,存在则返回true;
next():获取当前位置的元素,并同时将迭代器对象移向下一个位置,注意防止取出越界
Collection<String> list = new ArrayList<String>(); list.add("java"); list.add("mysql"); list.add("html"); list.add("css"); // [java, java, mysql, html, css] System.out.println(list); System.out.println("-----------------------------"); //1、得到当前集合的迭代器对象 Iterator<String> it = list.iterator(); String ele = it.next(); System.out.println(ele); System.out.println(it.next()); System.out.println(it.next()); System.out.println(it.next()); // System.out.println(it.next()); //java.util.NoSuchElementException 越界 // while循环 //2、定义while循环遍历 Iterator<String> it = list.iterator(); while (it.hasNext()){ //hasNext()判断是否有下一个元素 String ele = it.next(); //next方法会迭代器对象移动到下一个位置 System.out.println(ele); }
for each遍历
- 增强for循环:既可以遍历集合也可以遍历数组
- 他是JDK5之后出现的,其内部原理是一个Iterator迭代器,集合遍历相当于是迭代器的简化写法。
- 实现Iterable接口的才可以使用迭代器和for each,Collection接口已经实现了Iterable接口
//格式 for(元素数据类型 变量名:数组或者Collection集合){ //在此处使用变量即可,该变量就是元素 } //栗子 Collection<String> list = new ArrayList<>(); ... for(String ele : list){ System.out.println(ele); }
Collection结合Lambda遍历的API
栗子:
package com.djn.day1;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class LambdaIterator {
public static void main(String[] args) {
Collection<String> list = new ArrayList<String>();
list.add("java");list.add("mysql");
list.add("html");list.add("css");
//不简化。。。。。
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//Lambda表达式。。。。。。。。。。。。
list.forEach(s -> System.out.println(s) );
//或者。。。。。。。完全看不懂
list.forEach(System.out::println );
}
}
List集合
- List集合因为支持索引,所以多了很多索引操作的独特api,其他collection的功能也都继承了,
- void add(int index,e element):在此集合中的指定位置插入指定的元素
- E remove(int index,E element):修改指定索引处的元素,返回被修改的元素
- E get(int,index) 返回指定索引的元素
List<String> list = new ArrayList<String>(); list.add("java"); list.add("html"); list.add("mysql"); list.add("linux"); //在某个索引位置添加元素 list.add(2,"python"); System.out.println(list); //根据索引删除元素,返回被删除的元素 System.out.println(list.remove(2)); //根据索引获得元素 System.out.println(list.get(2)); //根据索引修改元素,返回值为被修改的元素 System.out.println(list.set(2,"董俊楠"));
List的实现类的底层原理
ArrayList
- ArrayList底层是基于数组实现的,根据查询元素快,增删相对慢
- LinkedList底层基于双链表表现得,查询元素慢,增删首位元素是非常快的
System.out.println("--------------简单for循环-----------------");
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
System.out.println("---------------Iterator迭代器----------------");
//迭代器
Iterator<String> it =list.iterator();
while(it.hasNext()){
String ele = it.next();
System.out.println(ele);
}
System.out.println("--------------增强for循环-----------------");
for (String s : list) {
System.out.println(s);
}
- ArrayList底层是基于数组实现的:根据索引定位元素快,增删元素需要做移位操作。
- 第一次创建层创建一个默认长度为 10的数组
LinkedList
addFirst()----->push():向集合首位加入 ,入栈
removeFirst()------>pop():移除第一个,弹栈
addLast()------>入队
removeFirst()----->出队
循环遍历删除元素
package com.djn.day2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("java");
list.add("java");
list.add("html");
list.add("mysql");
list.add("linux");
//删除所有的java
//1、迭代器删除
Iterator<String> it = list.iterator();
while (it.hasNext()){
String ele = it.next();
if (ele.equals("java")){
//使用迭代器删除当前所在元素,并且不会后移,不会漏掉元素
it.remove();
}
}
System.out.println(list);
//2、for循环倒着删除
for (int i = list.size()-1; i >=0 ; i--) {
String ele = list.get(i);
if (ele.equals("java")){
list.remove("java");
}
}
//3、for循环删除
for (int i = 0; i<list.size();i++) {
String ele = list.get(i);
if (ele.equals("java")){
list.remove("java");
}
i--; //删除后让索引后退,防止漏删
}
}
}
Set系列
set系列集合特点
- 无序:存放顺序不一致
- 不重复:可以去除重复
- 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引获取元素
Set集合实现类特点
- HashSet:无序,不重复,无索引
- LinkedHashSet:有序、不重复,无索引
- TreeSet:排序、不重复、无索引
HashSet
HashSet底层原理
- HashSet集合底层采取哈希表存储的数据
- 哈希表是一种对于增删改查数据性能都能较好的结构
哈希表的组成
- JDK8之前的,底层使用数组+链表组成
- JDK8开始后,底层采取数组+链表+红黑树组成
哈希值
- 是JDK根据对象的地址,按照某种规则算出来的int类型的数值
Object类的API
- public int hashCode():返回对象的哈希值
对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的
HsshSet1.7:数组+链表+(结合哈希算法)
- 创建一个默认长度16的数组,数组名table
- 根据元素的哈希值跟数组长度求余计算应存入位置(哈希算法)
- 判断当前位置是否为null,如果是null直接存入
- 如果位置部位null,表示有元素,则调用equals方法比较
- 如果一样,则不存,如果不一样,则存入数组,
- JDK 7新元素占老元素位置,之现象老元素
- JDK 8中新元素挂在老元素下面
JDK1.8版本开始HashSet原理解析
- 底层结构:哈希表(数组、链表、红黑树的结合体)
- 当挂在元素下面的数据过多时,查询性能降低,从JDK8开始后,当链表长度超过8的时候,自动转换为红黑树。
HashSet去重复原理
- 创建一个默认长度16的数组,数组名table
- 根据元素的哈希值跟数组长度求余计算应存入位置(哈希算法)
- 判断当前位置是否为null,如果是null直接存入
- 如果位置部位null,表示有元素,则调用equals方法比较
- 如果一样,则不存,如果不一样,则存入数组,
@Override
//重写hashCode和equals后,值相同的对象返回的hashcode相同
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name) &&
Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
public static void main(String[] args) {
Set<Student> sets = new HashSet<>();
Student s1 = new Student("aaa",12,"男");
Student s2 = new Student("bbb",13,"女");
Student s3 = new Student("ddd",14,"男");
Student s4 = new Student("ddd",14,"男");
sets.add(s1);
sets.add(s2);
sets.add(s3);
sets.add(s4);
System.out.println(s1.hashCode()); // 92624651
System.out.println(s2.hashCode()); //93571847
System.out.println(s3.hashCode()); //95487532
System.out.println(s4.hashCode()); //95487532
System.out.println(sets);
//[SetDemo3{name='bbb', age=13, sex='女'}, SetDemo3{name='ddd', age=14, sex='男'}, SetDemo3{name='aaa', age=12, sex='男'}]
}
LinkedHashSet
LinkedHashSet集合概述和特点
- 有序、不重复,无索引
- 这里的有序指的是保证存储和取出的元素顺序一致
- 原理:底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链的机制记录存储顺序。
TreeSet
特点概述
- 不重复、无索引、可排序
- 可排序:按照元素的大小默认升序(有小到大)排序
- TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好
TreeSet集合是一定要排序的,可以将元素按照指定元素的规则进行排序
TreeSet集合默认的规则
- 对于数值类型:Inteher,Double,官方默认按照大小进行升序排序
- 对于字符串类型:默认按照首字母的编号升序排序
- 杜宇自定义类型如Student对象,TreeSet无法直接排序
- 1、类实现Comparable接口,重写比较方法
- 2、集合自定义Comparator比较器对象,重写比较规则
package com.djn.d1_set;
import java.util.Set;
import java.util.TreeSet;
/*
* 观察TreeSet对于有特性的数据如何排序
* 学会自定义类型的对象进行指定规则排序
* */
public class SetDemo5 {
public static void main(String[] args) {
Set<Integer> set1 = new TreeSet<>();
set1.add(12);
set1.add(23);
set1.add(45);
set1.add(98);
System.out.println(set1); //[12, 23, 45, 98]
System.out.println("----------------");
Set<String> set2 = new TreeSet<>();
set2.add("angela");
set2.add("mysql");
set2.add("java");
set2.add("php");
set2.add("董槿兮");
set2.add("html");
set2.add("css");
set2.add("About");
System.out.println(set2); //[About, angela, css, html, java, mysql, php, 董槿兮]
// Exception in thread "main" java.lang.ClassCastException: com.djn.d1_set.Apple cannot be cast to java.lang.Comparable
}
}
对象类型排序
public class Apple implements Comparable<Apple>{ //继承Comparable接口,
private String name;
private String color;
private double price;
private int weight;
......
/*
* 方式一:类自定义比较规则
* */
@Override
public int compareTo(Apple o) {
return this.weight - o.weight; //按照重量排序,但是如果重量相等则会去重
return this.weight - o.weight >= 0 ? 1:-1; //如果两个相同,则认为第一个大
}
}
//测试
package com.djn.d1_set;
import java.util.Set;
import java.util.TreeSet;
/*
* 观察TreeSet对于有特性的数据如何排序
* 学会自定义类型的对象进行指定规则排序
* */
public class SetDemo5 {
public static void main(String[] args) {
Set<Apple> apples = new TreeSet<>();
apples.add(new Apple("红富士","红色",9.9,600));
apples.add(new Apple("青苹果","青色",15.9,300));
apples.add(new Apple("黄苹果","黄色",5.8,100));
apples.add(new Apple("苹果","苹果色",9.8,300));
System.out.println(apples);
//方式2
Set<Apple> apple = new TreeSet<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o2.getWeight()-o1.getWeight(); //o2 - o1 为倒叙
return Double.compare(o1.getPrice(),o2.getPrice()) >=0 ? 1 : -1; //浮点型建议使用compare比较;
}
});
//Lambda表达式简化
//t<Apple> apple = new TreeSet<>((o1,o2) ->Double.compare(o1.getPrice(),o2.getPrice()) >=0 ? 1 : -1 );
apple.add(new Apple("红富士","红色",9.9,600));
apple.add(new Apple("青苹果","青色",15.9,300));
apple.add(new Apple("黄苹果","黄色",5.8,100));
apple.add(new Apple("苹果","苹果色",9.8,300));
System.out.println(apple);
}
}
总结
- 如果希望元素可以重复,又有索引,索引查询要快?
- 用ArrayList集合,基于数组的(用的最多)
- 如果希望元素可以重复,又有索引,增删首操作快?
- 用LinkedList集合,基于链表的。
- 如果希望增删改查都快,但是元素不重复,无序、无索引
- 用HashSet集合,基于哈希表的。
- 如果希望增删改查都快,但是元素不重复,有序,无索引
- 用LinkedHashSet集合,基于哈希表和双链表
- 如要对对象进行排序
- 用TreSet集合,基于红黑树,后续也可以使用List集合实现排序
可变参数
- 可变参数用在形参中可以接收多个数据
- 可变参数的格式:数据类型...参数名称
package com.djn.d1_set;
import java.util.Arrays;
public class MethodDemo {
public static void main(String[] args) {
sum();
sum(10 );
sum(20,60);
}
public static void sum(int...nums){
System.out.println("元素个数" + nums.length);
System.out.println("元素内容" + Arrays.toString(nums));
}
}
可变参数的作用
- 传输参数非常灵活,方便,可以不传输参数,可传一个或多个,也可以传数组
- 可变擦拭农户在方法内部本质上就是一个数组
可变参数的注意事项:
- 一个形参列表中可变参数只能有一个
- 可变参数必须放在形参泪飙的最后
Collections集合工具类
Collections.addAll(list,"aaa","bbb","ccc","ddd"); 添加元素
Collections.shuffle(list); 打乱元素顺序 打乱list的顺序
Collections.sort(list1); 排序
package com.djn.d1_set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
Collections.addAll(list,"aaa","bbb","ccc","ddd"); //添加元素
System.out.println(list);
Collections.shuffle(list); //打乱元素顺序
System.out.println(list);
List<Integer> list1 = new ArrayList<>(); //排序
Collections.addAll(list,12,98,45,67);
Collections.sort(list1);
System.out.println(list);
}
}
Map
map集合概述和使用
- Map集合的每个元素的格式:key=value(键值对元素)
- Map集合也被称为键值对集合
Map集合整体格式
- Collection集合的格式:[元素1, 元素2, 元素3, ...]
- Map集合的完整格式:{key1=value1,key2=value2,....}
Map集合体系特点
- Map集合的特点都是由键决定的。
- Map集合的键是无序,不重复的,五索引的
- Map集合后面重复的键对应的值会覆盖前面重复键的值
- Map集合的键值对都可以为null。
Map集合实现类特点
- HashMap:元素按照键是无序,不重复,无索引,值不做要求(与map体系一致)
package MapTest;
import java.util.HashMap;
import java.util.Map;
public class MapDemo1 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("李宁",10);
map.put("红星",00);
map.put("李宁",9);
map.put(null,null);
System.out.println(map); // {null=null, 红星=0, 李宁=9}
}
- LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求
- TreeMap:元素按照键是排序,不重复,无索引的,值不做要求
Map常用方法
package MapTest;
import java.util.HashMap;
import java.util.Map;
public class MapDemo1 {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("李宁",10);
map.put("红星",00);
map.put("李宁",9);
map.put(null,null);
System.out.println(map);
System.out.println(map.isEmpty()); //false
Integer ln = map.get("李宁"); //返回的为value
map.remove("红星"); //返回值被删除的值
Integer hw = map.get("华为"); //若不存在,则返回null
System.out.println(map.containsKey("李宁")); //包含某个键
System.out.println(map.containsValue(10)); //包含某个键
Set<String> keys = map.keySet(); //获取map所有的键,set集合和map的键刚好都是无重复,[null, 红星, 李宁]
Collection<Integer> values = map.values(); //获取全部map的值,值是可以重复的,[null, 0, 9]
HashMap<String, Integer> map1 = new HashMap<>();
map1.put("董俊楠",1);
map1.put("刘梦媛",2);
HashMap<String, Integer> map2 = new HashMap<>();
map2.put("董嗷嗷",3);
map2.put("刘咩咩",4);
map1.putAll(map2); //把map2里的键值对拷贝到map1中一份
System.out.println(map1); //{董俊楠=1, 刘咩咩=4, 董嗷嗷=3, 刘梦媛=2}
System.out.println(map2); //{刘咩咩=4, 董嗷嗷=3}
}
}
HashMap遍历
package MapTest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapBianLi {
public static void main(String[] args) {
Map<String,Integer> map = new HashMap<>();
map.put("李宁",10);
map.put("红星",00);
map.put("李宁",9);
map.put("董俊楠",1);
map.put("刘梦媛",2);
map.put("董嗷嗷",3);
map.put("刘咩咩",4);
/*
* 方法1:键找值
* 1、先取到所有的键
* 2、在通过遍历键获取值
* */
Set<String> keys = map.keySet();
for (String key:keys) {
Integer value = map.get(key);
System.out.println(key+"=====>"+value);
}
/*
* 方法2:将map集合转为set,
*此方法面向对象
* */
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry:entries) {
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key+"--->"+value);
}
/*
* 方法:lambda表达式
* */
// map.forEach(new BiConsumer<String, Integer>() {
// @Override
// public void accept(String key, Integer value) {
// System.out.println(key+"--->"+value);
// }
// });
map.forEach((key,value)-> System.out.println(key+"--->"+value));
}
}
HashMap的特点和底层原理
- 有键决定:无序、不重复,无索引。HashMap底层是哈希表结构的
- 以来hashCode方法和equals方法保证键的唯一
- 如果键要存储的是自定义对象,需要重写hashCode和equals方法
- 基于哈希表,增删改查的性能都比较好
TreeMap
集合概述和特点
- 由键决定特性:不重复。无索引、可排序
- 可排序:按照键数据的大小默认升序(有小到大)排序。只能对键排序
- 注意:TreeMap集合一定要排序的,可以默认排序,也可以将键按照指定的规则进行排序
- TreeMap跟TreeSet一样,底层原理是一样的
标签:java,最全,list,System,println,可能,add,集合,out 来源: https://www.cnblogs.com/qurumei/p/16221782.html