标签:Map Set java map System 集合 println public out
目录
1.Set
1.1 Set集合概述和特点
Set集合特点
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通for循环遍历
- 迭代顺序随机
实例:
//HashSet:迭代顺序随机
public class SetTest {
public static void main(String[] args) {
//创建集合对象
Set<String> set = new HashSet<String>();
//添加元素
set.add("hello,world");
set.add("hello,java");
set.add("hello,python");
set.add("hello,python");
//遍历
for (String s :
set) {
System.out.println(s);
}
}
}
控制台输出:
1.2 哈希值
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的Int类型的数值
Object类中有一个方法可以获取对象的哈希值
- public int hashCode():返回对象的哈希值
对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现不同对象的哈希值相同
实例:
public class HashTest {
public static void main(String[] args) {
//创建学生对象
Student student = new Student("lucycia",18,"man");
//同一个对象多次调用hashCode()方法返回的哈希值相同
System.out.println(student.hashCode());//1769597131
System.out.println(student.hashCode());//1769597131
Student student2 = new Student("lucycia",18,"man");
System.out.println("==============");
//默认情况下,不同对象的哈希值是不同的
//通过方法重写,可以实现不同对象的哈希值是相同的
System.out.println(student2.hashCode());//1983747920
System.out.println("==============");
System.out.println("java".hashCode());//3254818
System.out.println("python".hashCode());//-973197092
System.out.println("html".hashCode());//3213227
System.out.println("html".hashCode());//3213227
System.out.println("==============");
System.out.println("重地".hashCode());//1179395
System.out.println("通话".hashCode());//1179395
}
}
控制台输出:
1.3 HshSet集合概述和特点
hashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和去除的元素顺序一致
- 没有带索引的方法,所以不能使用普通的for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
实例:
public class HashSetTest {
public static void main(String[] args) {
//创建集合对象
Set<String> hs = new HashSet<String>();
//添加元素
hs.add("hello,world");
hs.add("hello,java");
hs.add("hello,python");
hs.add("hello,python");
//遍历
for (String s :
hs) {
System.out.println(s);
}
}
}
控制台输出:
1.4 HashSet集合保证元素唯一性源码分析
HashSet集合添加一个元素的过程
Set<String> hs = new HashSet<String>();
//添加元素
hs.add("hello,world");
hs.add("hello,java");
hs.add("hello,python");
-----------------------------------------------
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//hash值是元素的hashCode()计算出来的
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果哈希表未初始化,就对其 进行初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//根据对象的哈希值计算对象的存储位置,如果该位置没有元素,就存储元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
/*
存储的元素和以前的元素比较哈希值
如果哈希值不同,会继续向下执行,把元素添加到集合
如果哈希值相同,会调用对象的equals()方法比较
如果返回false,会继续向下执行,把元素添加到集合
如果返回true,说明元素重复,不存值
*/
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
1.5 常见数据结构之哈希表
哈希表
- JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
- JDK8以后,在长度比较长的时候,底层实现了优化
1.6 LinkedHashSet集合概述和特点
LinkedHashSet集合特点
- 哈希表和链表实现的Set接口,迭代顺序是有序的
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
实例:
public class LinkedHashSetTest {
public static void main(String[] args) {
//创建集合对象
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
//添加元素
linkedHashSet.add("1");
linkedHashSet.add("2");
linkedHashSet.add("3");
//遍历对象
for (String s :
linkedHashSet) {
System.out.println(s);
}
}
}
控制台输出:
1.7 TreeSet集合概述和特点
TreeSet集合特点
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方法取决于构造方法
- TreeSet():根据其元素的自然排序进行排序
- TreeSet(Comparator comparator):根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
实例:
public class TreeSetTest {
public static void main(String[] args) {
//创建集合对象
TreeSet<Integer> ts = new TreeSet<>();
//添加元素
ts.add(1);
ts.add(2);
ts.add(3);
ts.add(4);
ts.add(5);
//遍历结合
for (Integer i :
ts) {
System.out.println(i);
}
}
}
控制台输出:
1.8 自然排序Comparable的使用
- 存储学生对象并遍历,创建TreeSet集合使用无参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
结论:
- 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo()方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
实例:
TreeSetTest2.java
public class TreeSetTest2 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> ts = new TreeSet<>();
//创建学生对象
Student s1 = new Student("tom1",18,"man");
Student s2 = new Student("tom2",28,"woman");
Student s3 = new Student("tom3",38,"man");
Student s4 = new Student("tom4",48,"woman");
Student s5 = new Student("tom5",48,"woman");
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for (Student s:
ts) {
System.out.println(s);
}
}
}
Student类
package com.lu.pojo;
public class Student implements Comparable<Student> {
private String name;
private int age;
private String sex;
public Student() {
}
public Student(String name, int age, String 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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
if (name != null ? !name.equals(student.name) : student.name != null) return false;
return sex != null ? sex.equals(student.sex) : student.sex == null;
}
@Override
public int compareTo(Student o) {
//return 0;
//return 1;
//return -1;
//按照年龄从小到大排序
System.out.println(this.age + " " + o.age);
int num = this.age - o.age;
//年龄相同时,按照姓名的字母顺序排序
int num2 = num==0?this.name.compareTo(o.name):num;
return num2;
}
}
控制台输出:
1.9 比较器排序Comparator的使用
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
实例:
public class TreeSetTest3 {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//创建学生对象
Student s1 = new Student("tom1",18,"man");
Student s2 = new Student("tom2",10,"woman");
Student s3 = new Student("tom3",38,"man");
Student s4 = new Student("tom4",48,"woman");
Student s5 = new Student("tom5",48,"woman");
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for (Student s:
ts) {
System.out.println(s);
}
}
}
控制台输出:
结论:
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare()方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件写
2.泛型
2.1 泛型概述
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型 方法、泛型接口。
泛型定义格式:
- <类型>:指定一种类型的格式。这里的类型可以看成是形参
- <类型1,类型2...>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
- 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
实例:
/*
Collection集合存储字符串并遍历
*/
public class GenericTest {
public static void main(String[] args) {
//创建集合对象
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("hello,java");
c.add("hello,python");
c.add("hello,html");
c.add("100");
Iterator<String> it = c.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
控制台输出:
2.2 泛型类
泛型类的定义格式:
- 格式:修饰符 class 类名<类型> {}
- 范例:public class GenericTest2<T> {}
此处的T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
实例:
Generic类
public class Generic<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
GenericTest3类
public class GenericTest3 {
public static void main(String[] args) {
Generic<String> g = new Generic<>();
g.setT("周星驰");
System.out.println(g.getT());
Generic<Integer> g2 = new Generic<Integer>();
g2.setT(55);
System.out.println(g2.getT());
}
}
控制台输出:
2.3 泛型方法
泛型方法的定义格式:
格式:修饰符 <类型> 返回值类型 方法名(类型 变量名){}
范例:public<T> void show(T t){}
实例:
Generic类
//泛型方法改进
public class Generic {
public <T> void show(T t) {
System.out.println(t);
}
}
GenericTest类
public class GenericTest {
public static void main(String[] args) {
Generic g = new Generic();
g.show("周星驰");
g.show(55);
g.show(true);
g.show(12.33);
}
}
控制台输出:
2.4 泛型接口
泛型接口的定义格式:
格式:修饰符 interface 接口名<类型> {}
范例:public interface Generic<T> {}
实例:
Generic接口
public interface Generic<T> {
void show(T t);
}
GenericImpl实现类
public class GenericImpl<T> implements Generic<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
GenericTest类
public class GenericTest {
public static void main(String[] args) {
Generic<String> g1 = new GenericImpl<String>();
g1.show("林青霞");
Generic<Integer> g2 = new GenericImpl<Integer>();
g2.show(12);
}
}
2.5 类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
- 类型通配符:<?>
- List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
- 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
- 类型通配符上限:<?extends类型>
- List<?extends Number>:它表示的类型是Number或者其子类
除了可以指定类型通配符的上限,我们也可以指定类型通配符下限
- 类型通配符下限:<?super>
- List<?super Number>:它表示的类型是Number或者父类型
实例:
public class GenericTest {
public static void main(String[] args) {
//类型通配符: <?>
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();
System.out.println("---------------");
//类型通配符的上限:<?extends 类型>
//List<? extends Number> list4 = new ArrayList<Object>();
List<? extends Number> list5 = new ArrayList<Number>();
List<? extends Number> list6 = new ArrayList<Integer>();
//类型通配符的下限:<?super 类型>
List<? super Number> list7 = new ArrayList<Object>();
List<? super Number> list8 = new ArrayList<Number>();
//List<? super Number> list9 = new ArrayList<Integer>();
}
}
2.6 可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
- 格式:修饰符 返回值类型 方法名(数据类型... 变量名){}
- 范例:public static int sum(int... a){}
可变参数注意事项
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在后面
实例:
public class ArgsTest {
public static void main(String[] args) {
System.out.println(sum(10,10));
System.out.println(sum(10,10,20));
System.out.println(sum(10,10,20,20));
System.out.println(sum(10,10,20,20,20));
System.out.println(sum(10,10,20,20,20,20));
System.out.println(sum(10,10,20,20,20,20,20));
System.out.println(sum(10,10,20,20,20,20,20,20));
}
public static int sum(int... a) {
int sum = 0;
for (int i :
a) {
sum += i;
}
return sum;
}
/* public static int sum(int a, int b) {
return a + b;
}
public static int sum(int a, int b, int c) {
return a + b + c;
}
public static int sum(int a, int b, int c, int d) {
return a + b + c + d;
}*/
}
控制台输出:
2.7 可变参数的使用
Arrays工具类中有一个静态方法:
- public static <T> List<T> asList(T... a):返回由指定数组支持的固定大小的列表
- 返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
- public static <E> List<E> of(E... elements):返回包含任意数量元素的不可变列表
- 返回的集合不能做增删改操作
Set接口中有一个静态方法:
- public static <E> Set<E> of(E... elements):返回一个包含任意数量元素的不可变结合
- 在给元素的时候,不能给重复的元素
- 返回的集合不能做增删操作,没有修改的方法
实例:
public class ArgsTest2 {
public static void main(String[] args) {
//返回由指定数组支持的固定大小的列表
List<String> list = Arrays.asList("java", "python", "html");
/*list.add("css");//UnsupportedOperationException*/
/*list.remove("html");//UnsupportedOperationException*/
list.set(1,"javascript");
System.out.println(list);
//返回包含任意数量元素的不可变列表
List<String> list2 = List.of("java", "python", "html", "html");
/*list2.add("css");//UnsupportedOperationException*/
/*list2.remove("html");//UnsupportedOperationException*/
/*list2.set(1,"javascript");//UnsupportedOperationException*/
System.out.println(list2);
//返回一个包含任意数量元素的不可变结合
/*Set<String> set = Set.of("java", "python", "html", "html");//IllegalArgumentException: duplicate element: html*/
Set<String> set = Set.of("java", "python", "html");
/* set.add("css");//UnsupportedOperationException
set.remove("css");//UnsupportedOperationException*/
System.out.println(set);
}
}
控制台输出:
3.Map
3.1 Map集合概述和使用
Map集合概述
- Interface Map<K,V> K:键的类型; V:值的类型
- 将键映射到值的对象,不能包含重复的键,每个键可以映射到最多一个值
- 举例:学生的学号和姓名
001 周星驰
002 加多宝
003 刘德华
创建Map集合的对象
- 多态的方式
- 具体的实现类HashMap
实例:
public class MapTest {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("001", "周星驰");
map.put("002", "加多宝");
map.put("003", "刘德华");
map.put("003", "张家辉");
System.out.println(map);
}
}
控制台输出:
3.2 Map集合的基本功能
方法名 | 说明 |
| 添加元素 |
| 根据键删除键值对元素 |
| 移除所有的键值对元素 |
| 判断集合是否包含指定的键 |
| 判断集合是否包含指定的值 |
| 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
实例:
public class MapTest2 {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<>();
//添加集合元素
map.put("001", "周星驰");
map.put("002", "加多宝");
map.put("003", "刘德华");
System.out.println(map);
//根据键删除键值对元素
System.out.println(map.remove("001"));
System.out.println(map);
//判断集合是否包含指定的键
System.out.println(map.containsKey("002"));
//判断集合是否包含指定的值
System.out.println(map.containsValue("加多宝"));
//判断集合是否为空
System.out.println(map.isEmpty());
//集合的长度,也就是集合中键值对的个数
System.out.println(map.size());
//移除所有的键值对元素
map.clear();
System.out.println(map);
}
}
控制台输出:
3.3 Map集合的获取功能
方法名 | 说明 |
| 根据键获取值 |
| 获取所有键的集合 |
| 获取所有值的集合 |
| 获取所有键值对对象的集合 |
实例:
/*
V get(Object key) 根据键获取值
Set<K> keySet() 获取所有键的集合
Collection<V> values() 获取所有值的集合
Set<Map.Entry<K, V>> entrySet() 获取所有键值对对象的集合
*/
public class MapTest3 {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<>();
//添加集合元素
map.put("星爷", "周星驰");
map.put("007", "加多宝");
map.put("华仔", "刘德华");
System.out.println(map);
//V get(Object key) 根据键获取值
System.out.println("=====================");
System.out.println(map.get("星爷"));
//Set<K> keySet() 获取所有键的集合
System.out.println("=====================");
System.out.println(map.keySet());
System.out.println("=====================");
Set<String> keySet = map.keySet();
for (String s :
keySet) {
System.out.println(s);
}
//Collection<V> values() 获取所有值的集合
System.out.println("=====================");
System.out.println(map.values());
//Set<Map.Entry<K, V>> entrySet() 获取所有键值对对象的集合
System.out.println("=====================");
System.out.println(map.entrySet());
}
}
控制台输出:
3.4 Map集合的遍历(方式1)
- 首先获取map集合所有的键集合
- 将键集合保存在set当中,然后遍历用map的get方法获得
实例:
public class MapTest {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<>();
//添加集合元素
map.put("星爷", "周星驰");
map.put("007", "加多宝");
map.put("华仔", "刘德华");
System.out.println(map);
Set<String> set = map.keySet();
for (String s :
set) {
System.out.println(map.get(s));
}
}
}
控制台输出:
3.5 Map集合的遍历(方式2)
- 首先获取所有键值对对象的集合
- 然后遍历每一个键值对对象
- 根据键值对对象获取键和值
实例:
public class MapTest2 {
public static void main(String[] args) {
//创建集合对象
Map<String, String> map = new HashMap<>();
//添加集合元素
map.put("星爷", "周星驰");
map.put("007", "加多宝");
map.put("华仔", "刘德华");
System.out.println(map);
//获取所有键值对对象的集合
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for (Map.Entry<String, String> me :
entrySet) {
String key = me.getKey();
String value = me.getValue();
System.out.println(key + " " + value);
}
}
}
控制台输出:
4. Collections
4.1 Collections概述和使用
Collections类的概述
- 是针对集合操作的工具类
Collections类的常用方法
方法名 | 说明 |
| 将指定的列表按升序排序 |
| 反转指定列表中元素的顺序 |
| 使用默认的随机元随机排列指定的列表 |
实例:
public class CollectionsTest {
public static void main(String[] args) {
//创建集合对象
List<Integer> list = new ArrayList<>();
//添加元素
list.add(60);
list.add(20);
list.add(10);
list.add(40);
list.add(50);
System.out.println(list);
//public static <T extends Comparable<? super T>> void sort(List<T> list)
Collections.sort(list);
System.out.println(list);
//public static void reverse(List<?> list)
Collections.reverse(list);
System.out.println(list);
//public static void shuffle(List<?> list)
Collections.shuffle(list);
System.out.println(list);
}
}
控制台输出:
标签:Map,Set,java,map,System,集合,println,public,out 来源: https://blog.csdn.net/ypxcan/article/details/119359689
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。