set系列集合
无序 :存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。
Set集合实现类特点
HashSet : 无序、不重复、无索引。(长子)
LinkedHashSet:有序、不重复、无索引。(孙子)
TreeSet:排序、不重复、无索引。(兄弟)
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
public class test1 {
public static void main(String[] args) {
//经典代码
Set<String> set =new HashSet<>();
set.add("我");
set.add("我");
set.add("是");
set.add("是");
set.add("笨");
set.add("蛋");
System.out.println(set);
//不重复 无序 无索引 (对外没有提供方法)
}
}
结果
[我, 笨, 蛋, 是]
HashSet底层原理
HashSet集合底层采取哈希表存储的数据。
哈希表是一种对于增删改查数据性能都较好的结构
哈希值
是JDK根据对象的地址,按照某种规则算出来的int类型的数值
public int hashCode():返回对象的哈希值
对象的哈希值特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的
public class test2 {
public static void main(String[] args) {
//获取对象的哈希值
String name="wsbd";
System.out.println(name.hashCode());
System.out.println(name.hashCode());
String nam2="bd";
System.out.println(nam2.hashCode());
System.out.println(nam2.hashCode());
}
}
结果
3658782
3658782
3138
3138
set集合去重复
public class test3 {
public static void main(String[] args) {
//去重复
Set<students> set =new HashSet<>();
students s1=new students("牛马",18,'男');
students s2=new students("牛马",18,'男');
students s3=new students("笨蛋",20,'男');
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
set.add(s1);
set.add(s2);
set.add(s3);
System.out.println(set);
}
}
public class students {
private String name;
private int age;
private char sex;
public students(){}
public students(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@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 && sex == students.sex && Objects.equals(name, students.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, sex);
}
@Override
public String toString() {
return "students{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
结果
910182133
910182133
972472293
[students{name='笨蛋', age=20, sex=男}, students{name='牛马', age=18, sex=男}]
LinkedHashSet集合概述和特点
有序、不重复、无索引
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。
Set<String> sets = new LinkedHashSet<>(); // 有序 不重复 无索引
TreeSet集合概述和特点
不重复、无索引、可排序 可排序:
按照元素的大小默认升序(有小到大)排序。
TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。
TreeSet集合自定义排序规则有 2种方式。
类实现Comparable接口,重写比较规则。
集合自定义Comparator比较器对象,重写比较规则。
public class test5 {
public static void main(String[] args) {
Set<Integer> set=new TreeSet<>();// 不重复 无索引 可排序
set.add(2);
set.add(24);
set.add(10);
set.add(25);
System.out.println(set);
Set<String> set1 =new TreeSet<>();// 不重复 无索引 可排序
set1.add("A");
set1.add("a");
set1.add("牛");
set1.add("马");
set1.add("f");
System.out.println(set1);
Set<Apple> set2=new TreeSet<>();
Apple a =new Apple("红苹果","红色",6.0,500);
Apple a1 =new Apple("蛇红苹果","红色",54.0,300);
Apple a3 =new Apple("黄苹果","黄色",32.0,600);
Apple a2 =new Apple("青苹果","青色",2.0,250);
set2.add(a);
set2.add(a1);
set2.add(a2);
set2.add(a3);
System.out.println(set2);
}
}
public class Apple implements Comparable<Apple>{
private String name;
private String color;
private double price;
private int weight;
public Apple() {
}
public Apple(String name, String color, double price, int weight) {
this.name = name;
this.color = color;
this.price = price;
this.weight = weight;
}
/比较方法
@Override
public int compareTo(Apple o) {
// 按照重量进行比较的
return this.weight - o.weight ; // 去重重量重复的元素
// return this.weight - o.weight >= 0 ? 1 : -1; // 保留重量重复的元素
}
}
结果是
[2, 10, 24, 25]
[A, a, f, 牛, 马]
[Apple{name='青苹果', color='青色', price=2.0, weight=250},
Apple{name='蛇红苹果', color='红色', price=54.0, weight=300},
Apple{name='红苹果', color='红色', price=6.0, weight=500},
Apple{name='黄苹果', color='黄色', price=32.0, weight=600}]
总结
如果希望元素可以重复,又有索引,索引查询要快?
用ArrayList集合,基于数组的。(用的最多)
如果希望元素可以重复,又有索引,增删首尾操作快?
用LinkedList集合,基于链表的。
如果希望增删改查都快,但是元素不重复、无序、无索引。
用HashSet集合,基于哈希表的。
如果希望增删改查都快,但是元素不重复、有序、无索引。
用LinkedHashSet集合,基于哈希表和双链表。
如果要对对象进行排序。
用TreeSet集合,基于红黑树。后续也可以用List集合实现排序
可变参数
可变参数用在形参中可以接收多个数据。
可变参数的格式:数据类型...参数名称
传输参数非常灵活,方便。可以不传输参数,可以传输1个或者多个,也可以传输一个数组
可变参数在方法内部本质上就是一个数组。
可变参数的注意事项:
1.一个形参列表中可变参数只能有一个
2.可变参数必须放在形参列表的最后面
public class test {
public static void main(String[] args) {
//不穿参数
sum();//可以不传
sum(1);//传一个
sum(1,2);//传两个
sum(new int[]{1, 3,4 ,6,7});//传数组
}
public static void sum(int ...nums){//形参列表中参数只有一个,然后就是形参必须放在可变参数前面
System.out.println("个数"+nums.length);
System.out.println("内容是"+Arrays.toString(nums));
}
}
集合工具类Collections
java.utils.Collections:是集合工具类 Collections并不属于集合,是用来操作集合的工具类。 Collections有几个常用的API: - public static <T> boolean addAll(Collection<? super T> c, T... elements) 给集合对象批量添加元素! - public static void shuffle(List<?> list) :打乱集合顺序。 - public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。 - public static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序。
public class test {
public static void main(String[] args) {
List<String > name=new ArrayList<>();
Collections.addAll(name ,"牛马","笨蛋","张三","李四");// 给集合对象批量添加元素!
System.out.println(name);
Collections.shuffle(name);//打乱集合顺序。
System.out.println(name);
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 12, 23, 2, 4);//将集合中元素按照默认规则排序
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
结果
[牛马, 笨蛋, 张三, 李四]
[笨蛋, 张三, 牛马, 李四]
[12, 23, 2, 4]
[2, 4, 12, 23]
Collections排序相关API
使用范围:只能对于List集合的排序。
法1
public static <T> void sort(List<T> list)
法2
public static <T> void sort(List<T> list,Comparator<? super T> c)
方式二:sort方法自带比较器对象
Collections.sort(apples, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return Double.compare(o1.getPrice() , o2.getPrice()); // 按照价格排序!!
}
});
Collections.sort(apples, ( o1, o2) -> Double.compare(o1.getPrice() , o2.getPrice()) );
System.out.println(apples);
Map集合的概述和作用
Map集合是一种双列集合,每个元素包含两个数据。
Map集合的每个元素的格式:key=value(键值对元素)。
Map集合也被称为“键值对集合
Map集合整体格式
Collection集合的格式: [元素1,元素2,元素3..]
Map集合的完整格式:{key1=value1 , key2=value2 , key3=value3 , ...}
Mapj集合体系
接口 Map 。。。
实现类 剩下都是
使用最多的是HsahMap
Map特点
Map集合的特点都是由键决定的。
Map集合的键是无序,不重复的,无索引的,值不做要求(可以重复)。
Map集合后面重复的键对应的值会覆盖前面重复键的值。
Map集合的键值对都可以为null。
public class test {
public static void main(String[] args) {
Map<String,Integer > map=new HashMap();//经典代码
// Map<String,Integer> map1=new LinkedHashMap<>();
map.put("我是笨蛋",666);
map.put("可乐",3);
map.put("null",0);
map.put("可乐",5);// 覆盖前面的数据
System.out.println(map);
}
}
{我是笨蛋=666, null=0, 可乐=5}
Map是双列集合的祖宗接口,它的功能是全部双列集合都可以继承使用的
目标:Map集合的常用API(重点中的重点)
- public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。 - public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。 - public V get(Object key) 根据指定的键,在Map集合中获取对应的值。 - public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。 - public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。 - public boolean containKey(Object key):判断该集合中是否有此键。 - public boolean containValue(Object value):判断该集合中是否有此值。
添加元素: 无序,不重复,无索引
Map<String , Integer> maps = new HashMap<>();
maps.put("苹果",10);
maps.put("=牛马",20);
清空集合
maps.clear();
判断集合是否为空,为空返回true ,反之!
System.out.println(maps.isEmpty());
.根据键获取对应值:public V get(Object key)
Integer key = maps.get("牛马");
System.out.println(key);
根据键删除整个元素。(删除键会返回键的值)
System.out.println(maps.remove("苹果"));
结果 10
判断是否包含某个键 ,包含返回true ,反之
System.out.println(maps.containsKey("牛马"));
结果 true
判断是否包含某个值
System.out.println(maps.containsValue(10)); //ture
获取全部键的集合:public Set<K> keySet()
Set<String> keys = maps.keySet();
System.out.println(keys);
获取全部值的集合:Collection<V> values();
Collection<Integer> values = maps.values();
System.out.println(values);
集合的大小
System.out.println(maps.size());
结果 2
Map中的遍历的方式有3种
方式一:键找值”的方式遍历Map集合。
1.先获取Map集合的全部键的Set集合。
2.遍历键的Set集合,然后通过键找值。
public class test {
public static void main(String[] args) {
Map<String,Integer> map=new HashMap<>();
map.put("苹果",10);
map.put("牛马",20);
map.put("老6",300);
map.put("老八",666);
Set<String> m=map.keySet();
for (String mm : m) {
int zhi=map.get(mm);
System.out.println(mm+"====>"+ zhi);
}
}
}
方式二 键值对”的方式遍历: 1.把Map集合转换成一个Set集合:Set<Map.Entry<K, V>> entrySet(); 2.此时键值对元素的类型就确定了,类型是键值对实体类型:Map.Entry<K, V> 3.接下来就可以用foreach遍历这个Set集合,类型用Map.Entry<K, V>
public class test2 {
public static void main(String[] args) {
Map<String,Integer> map=new HashMap<>();
map.put("苹果",10);
map.put("牛马",20);
map.put("老6",300);
map.put("老八",666);
System.out.println(map);
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);
}
}
}
HashMap的特点
HashMap是Map里面的一个实现类。特点都是由键决定的:无序、不重复、无索引
’没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
HashMap跟HashSet底层原理是一模一样的,都是哈希表结构,只是HashMap的每个元素包含两个值而已。
由键决定:无序、不重复、无索引。
HashMap底层是哈希表结构的。
依赖hashCode方法和equals方法保证键的唯一。
如果键要存储的是自定义对象,需要重写hashCode和equals方法。
基于哈希表。增删改查的性能都较好。
TreeMap
TreeMap集合的特点是怎么样的?
根据键可排序、不重复、无索引
底层基于红黑树实现排序,增删改查性能较好
TreeMap集合自定义排序规则有2种方式
类实现Comparable接口,重写比较规则。
集合自定义Comparator比较器对象,重写比较规则。
Map集合实现类特点
HashMap:元素按照键是无序,不重复,无索引,值不做要求,基于哈希表(与Map体系一致) LinkedHashMap:元素按照键是有序,不重复,无索引,值不做要求,基于哈希表
TreeMap:元素只能按照键排序,不重复,无索引的,值不做要求,可以做排序
集合的嵌套
public class MapTest4 {
public static void main(String[] args) {
// 1、要求程序记录每个学生选择的情况。
// 使用一个Map集合存储。
Map<String, List<String>> data = new HashMap<>();
// 2、把学生选择的数据存入进去。
List<String> selects = new ArrayList<>();
Collections.addAll(selects, "A", "C");
data.put("罗", selects);
List<String> selects1 = new ArrayList<>();
Collections.addAll(selects1, "B", "C" , "D");
data.put("胡", selects1);
List<String> selects2 = new ArrayList<>();
Collections.addAll(selects2 , "A", "B", "C" , "D");
data.put("刘", selects2);
System.out.println(data);
// 3、统计每个景点选择的人数。
Map<String, Integer> infos = new HashMap<>(); // {}
// 4、提取所有人选择的景点的信息。
Collection<List<String>> values = data.values();
System.out.println(values);
// values = [[A, B, C, D], [B, C, D], [A, C]]
// value
for (List<String> value : values) {
for (String s : value) {
// 有没有包含这个景点
if(infos.containsKey(s)){
infos.put(s, infos.get(s) + 1);
}else {
infos.put(s , 1);
}
}
}
System.out.println(infos);
}
}