第08章 Java集合
创作日期:2021-11-11
1.Java集合框架概述
1.1 数组到集合的引申
面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用Array存储对象方面具有一些弊端,而Java集合就像是一种容器,可以动态地把多个对象的引用放入容器中,还可用于保存具有映射关系的关联数组。
数组在内存存储方面的特点:
- 数组初始化以后,长度就确定了
- 数组声明的类型,就决定了进行元素初始化时的类型
数组在存储数据方面的弊端:
- 数组初始化以后,长度就不可改变了,不便于扩展
- 数组中提供的属性和方法少,不便于进行添加,删除,插入等操作,且效率不高,同时无法直接获取存储元素的个数
- 数组存储的数据是有序的,可以重复的,存储数据的特点比较单一
1.2 Java集合的框架体系
Java集合可分为 Collection 和 Map 两种体系:
- Collection接口:单列数据,定义了存取一组对象的方法的集合
- List:元素有序,可重复的集合
- Set:元素无序,不可重复的集合
- Map接口:双列数据,保存具有影射关系“key-value”键值对的集合
Collection接口继承树
Map接口继承树
2.Collection的接口方法
import java.util.*;
/**
* Welcome to Idea Java
*
* @author Administrator
* @date 2021/11/26 8:29
**/
public class CollectionTest {
public static void main(String[] args) {
Collection collection1 = new ArrayList();
//add(Object e):将元素e添加到集合collection中
collection1.add(123);
collection1.add("lisi");
collection1.add(new Date());
System.out.println(collection1);// [123, lisi, Fri Nov 26 08:36:35 CST 2021]
//size():获取元素个数
System.out.println(collection1.size());// 3
//addAll():将集合a中的元素全部添加到集合b中
Collection collection2 = new ArrayList();
collection2.addAll(collection1);
System.out.println(collection2);// [123, lisi, Fri Nov 26 08:39:39 CST 2021]
//clear():将集合元素清空
collection2.clear();
//isEmpty():判断集合是否为空
System.out.println(collection2.isEmpty());// true
//contains(Object):判断集合是否包含某个元素
System.out.println(collection1.contains("lisi"));// true
//containsAll(Collection b):判断集合b中的元素是否都存在于集合a中
collection2.add("zan");
collection2.add("lisi");
System.out.println(collection1.containsAll(collection2));// false
//remove():移除集合中的某个元素
System.out.println(collection1.remove("lisi"));// true
System.out.println(collection1);// [123, Fri Nov 26 08:48:22 CST 2021]
//removeAll():从当前集合a中移除与集合b中相同的所有元素
collection2.add(123);
System.out.println(collection2);// [zan, lisi, 123]
System.out.println(collection2.removeAll(collection1));// true
System.out.println(collection1);// [123, Fri Nov 26 08:55:48 CST 2021]
System.out.println(collection2);// [zan, lisi]
//retainAll():获取当前集合a与集合b中的交集,并返回给当前集合
collection1.add("lisi");
System.out.println(collection1);//[123, Fri Nov 26 08:58:37 CST 2021, lisi]
System.out.println(collection1.retainAll(collection2));// true
System.out.println(collection1);// [lisi]
//equals():判断集合a与集合b是否相同,需要元素全部相同才能返回true
System.out.println(collection1.equals(collection2)); // false
Collection collection3 = new ArrayList();
collection3.add("lisi");
System.out.println(collection1.equals(collection3));// true
//hashCode():返回当前集合的哈希值
System.out.println(collection1.hashCode());
//toArray():集合向数组的转型
Object[] objects = collection2.toArray();
System.out.println(Arrays.toString(objects)); // [zan, lisi]
//toList():数组向集合的转型
List<Object> objects1 = Arrays.stream(objects).toList();
System.out.println(objects1);// [zan, lisi]
}
}
3.Iterator迭代器遍历集合
3.1 Iterator迭代器的概述
- Iterator对象称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素。
- GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生。
- Collection接口继承了java.lang.Iterable接口,该接口有一个itreator()方法,那么所有实现了Collection接口的集合类都有一个treator()方法,用以返回一个实现了Iterator接口的对象。
- Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。
- 集合对象每次调用itreator()方法都得到一个全新的迭代对象,默认游标都在集合的第一个元素之前。
3.2 Iterator迭代器的使用
import java.util.*;
// 集合元素的遍历操作 使用迭代器Iterator接口
public class CollectionTest {
public static void main(String[] args) {
Collection collection1 = new ArrayList();
collection1.add(123);
collection1.add("lisi");
collection1.add(new Date());
//集合实现Iterator接口
Iterator iterator = collection1.iterator();
//使用迭代器Iterator接口对象循环遍历
while(iterator.hasNext()){
//hasNext():判断是否还有下一个元素
//next():指针下移,将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
//使用迭代器remove()方法对集合元素进行删除
Iterator iterator1 = collection1.iterator();
while(iterator1.hasNext()){
Object next = iterator1.next();
if ("lisi".equals(next)){
iterator1.remove();
}
}
}
}
注意:Iterator可以删除集合的元素,但是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法;若果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove都会报异常。
3.3 集合遍历的另一种实现方式
增强for循环:foreach()的使用:
import java.util.*;
// 增强for循环:foreach()的使用
public class CollectionTest {
public static void main(String[] args) {
Collection collection1 = new ArrayList();
collection1.add(123);
collection1.add("lisi");
collection1.add(new Date());
for (Object o:collection1) {
System.out.println(o);
}
}
}
4.Collection子接口一:List
4.1 List接口概述
- 鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组
- List集合类中元素有序,且可重复,集合中的每个元素都具有其对应的顺序索引。
- List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
- JDK API中List接口的实现类常用的有:ArrayList,LinkedList和Vector。
4.2 List接口的方法
List除了从Collection集合继承的方法外,List集合还添加了一些根据索引来操作集合元素的方法:
- void add(int index,Object ele):在index位置插入ele元素
- boolean addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来
- Object get(int index):获取指定index位置的元素
- int indexOf(Object obj):返回obj在当前集合中首次出现的位置
- int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
- Object remove(int index):移除指定index位置的元素,并返回此元素
- Object set(int index,Object obj):设置指定index位置的元素为ele
- List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合
import java.util.*;
//List接口的方法
public class CollectionTest {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
ArrayList arrayList1 = new ArrayList();
arrayList.add(1);
arrayList.add(3);
arrayList.add(5);
arrayList.add(6);
arrayList1.add(4);
//void add(int index,Object ele):在index位置插入ele元素
arrayList.add(1,2);
System.out.println(arrayList);//[1, 2, 3, 5, 6]
//boolean addAll(int index,Collection eles):从index位置开始将eles中的所有元素添加进来
arrayList.addAll(3,arrayList1);
System.out.println(arrayList);//[1, 2, 3, 4, 5, 6]
//Object get(int index):获取指定index位置的元素
System.out.println(arrayList.get(1));//2
//int indexOf(Object obj):返回obj在当前集合中首次出现的位置
System.out.println(arrayList.indexOf(1));//0
//int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
System.out.println(arrayList.lastIndexOf(1));//0
//Object remove(int index):移除指定index位置的元素,并返回此元素
System.out.println(arrayList1);//[4]
System.out.println(arrayList1.remove(0));//4
System.out.println(arrayList1);//[]
//Object set(int index,Object obj):设置指定index位置的元素为ele
System.out.println(arrayList);//[1, 2, 3, 4, 5, 6]
arrayList.set(0,0);
System.out.println(arrayList);//[0, 2, 3, 4, 5, 6]
//List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合
System.out.println(arrayList.subList(1,6));//[2, 3, 4, 5, 6]
}
}
4.3 List实现类之一:ArrayList
- ArrayList是List接口的典型实现类,主要实现类
- 本质上,ArrayList是对象引用的一个”变长“数组
- ArrayList的JDK 1.8之前与之后的实现区别?
- JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
- JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加一个元素时再创建一个容量为10的数组
- ArrayList.asList()方法返回的List集合,既不是ArrayList实例,也不是Vector实例。ArrayList.asList()方法返回值是一个固定长度的List集合
4.4 List实现类之二:LinkedList
LinkedList:双向链表,内部没有声明数组。而定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构,对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高。Ndoe除了保存数据,还定义了两个变量: prev:变量记录前一个元素的位置;next:变量记录下一个元素的位置。
新增方法:
- void addFirst(Object obj)
- void addLast(Object obj)
- Object getFirst()
- Object getLast()
- Object removeFirst()
- Object removeLast()
4.5 List实现类之三:Vector
- Vector的内部实现类似于ArrayList,Vector也是基于一个容量能够动态增长的数组来实现的,该类是JDK1.0版本添加的类,它的很多实现方法都加入了同步语句,因此是线程安全的(但Vector其实也只是相对安全,有些时候还是要加入同步语句来保证线程的安全)。
- Vector继承于AbstractList,实现了List接口,可以对它进行队列操作;实现了RandmoAccess接口,即提供了随机访问功能;实现了Cloneable接口,能被克隆;实现了Serializable接口,因此它支持序列化,能够通过序列化传输。
4.6 ArrayList,LinkedList,Vector三者的异同
- ArrayList:作为List接口的主要实现类,线程不安全,效率高,底层使用Object[] elementData存储。
- LinkedList:对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率比
- ArrayList高,底层使用双向链表。
- Vector:作为List接口的古老实现类,线程安全,效率低,底层使用Object[] elementData存储。
5.Collection子接口二:Set
5.1 Set接口概述
Set:存储无序的,不可重复的数据
- 无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。
- 不可重复性:保证添加的元素按照equals()判断时,不能返回true。即相同的元素只能添加一个。
- Set接口是Collection的子接口,set接口没有提供额外的方法
- Set集合不允许包含相同的元素,如果试着把两个相同的元素加入同一个Set集合中,则添加操作失败。
- Set判断两个对象是否相同不是使用 == 运算符,而是根据equals()方法
5.2 Set实现类之一:HashSet
- HashSet 是Set 接口的典型实现,大多数时候使用Set集合时都使用这个实现类。
- HashSet 按 Hash算法来存储集合中的元素,因此具有很好的存取,查找,删除性能。
- HashSet 具有以下特点:不能保证元素的排列顺序;HashSet不是线程安全;集合元素可以说null
- HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode()方法比较相等,并且两个对象的 equals()方法返回值也相等。
- 对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等原则。即:“相等的对象必须具有相等的散列码”。
5.3 Set实现类之二:LinkedHashSet
- LinkedHashSet是HashSet的子类
- LinkedHashSet根据元素的hashCode值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
- LinkedHashSet插入性能略低于HashSet,但在迭代访问Set里的全部元素时有很好的性能。
- LinkedHashSet不允许集合元素重复。
5.4 Set实现类之二:TreeSet
- TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
- TreeSet底层使用红黑树结构存储数据
- 新增的方法如下:(了解)
- Comparator comparator()
- Object first()
- Object last()
- Object lower(Object e)
- Object higher(Object e)
- SortedSet subSet(fromElement,toElement)
- SortedSet headSet(toElement)
- SortedSet tailSet(fromElement)
- TreeSet 两种排序方法:自然排序和定制排序。默认情况下,ThreeSet采用自然排序。
5.5 TreeSet的练习实例
import java.util.Comparator;
import java.util.TreeSet;
/**
* Welcome to Idea Java
*
* @author Administrator
* @date 2021/11/27 9:55
**/
public class SetTest {
public static void main(String[] args) {
//为treeSet设置定制排排序,安装生日进行排序,每次创建都进行对比排序
TreeSet treeSet = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Employee && o2 instanceof Employee) {
Employee employee1 = (Employee) o1;
Employee employee2 = (Employee) o2;
MyData data1 = employee1.getBirthday();
MyData data2 = employee2.getBirthday();
int minYear = data1.getYear() - data2.getYear();
if (minYear != 0) return minYear;
int minMouth = data1.getMonth() - data2.getMonth();
if (minMouth != 0) return minMouth;
return data1.getDay() - data2.getDay();
}
return 0;
}
});
Employee employee1 = new Employee("阿哥", 12, new MyData(1998, 03, 25));
Employee employee2 = new Employee("曹哥", 45, new MyData(1991, 02, 03));
Employee employee3 = new Employee("一哥", 25, new MyData(1988, 05, 22));
Employee employee4 = new Employee("帝哥", 50, new MyData(1988, 05, 13));
Employee employee5 = new Employee("逼哥", 30, new MyData(1977, 12, 18));
treeSet.add(employee1);
treeSet.add(employee2);
treeSet.add(employee3);
treeSet.add(employee4);
treeSet.add(employee5);
for (Object O : treeSet) {
System.out.println(O);
}
}
}
//Employee类
class Employee implements Comparable {
private String name;
private int age;
private MyData birthday;
public Employee() {
}
public Employee(String name, int age, MyData birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
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 MyData getBirthday() {
return birthday;
}
public void setBirthday(MyData birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
//Employee实现Comparable接口,按照name排序,自然排序
@Override
public int compareTo(Object o) {
if (o instanceof Employee) {
Employee e = (Employee) o;
return e.name.compareTo(this.name);
}
return 0;
}
}
//MyData类
class MyData {
private int year;
private int month;
private int day;
public MyData() {
}
public MyData(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public String toString() {
return "MyData{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
6.Map接口
6.1 Map接口继承树
6.2 Map的实现类结构
- Map:双列数据,存储key-value对的数据
- HashMap:作为Map的主要实现类,线程不安全,效率高,存储null的key和value,底层:数据+链表+红黑树
- LinkedHashMap:保证在遍历Map元素时,可以按照添加的顺序实现遍历;在原有的HashMap基础上,添加了一对指针,指向前一个和后一个;对于频繁的遍历操作,此类执行效率高于HashMap
- TreeMap:保证安装添加的key-value对进行排序,实现排序遍历,此时考虑key的自然排序或定制排序,底层使用红黑树
- Hashtable:古老的实现类:线程安全,效率低,不能存储null的key和value
- Properties:常用来处理配置文件,key和value都是String类型
6.3 Map接口的理解
- Map中的key:无序的,不可重复的。使用Set存储所有的key,key所在的类要重写equals()方法和hashCode()方法。
- Map中的value:无序的,可重复的,使用Collection存储所有的value,value所在的类要实现equals()方法。
- Map中的entry:一个键值对:key-value构成了一个Entry对象,无序的,不可重复的,使用Set存储所有的entry。
6.4 Map接口中的常用方法
- 添加,删除,修改操作
Object put(Object key,Object value):将指定键值对添加到或修改当前map对象当中
void putAll(Map m):将m中的所有键值对存放到当前map中
void clear():清空当前map中的所有数据
import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map map1 = new HashMap();
//Object put(Object key,Object value):将指定键值对添加到或修改当前map对象当中
map1.put("lisi",1);
map1.put("zhangsan",2);
map1.put("wanger",3);
System.out.println(map1);//{lisi=1, zhangsan=2, wanger=3}
Map map2 = new HashMap();
map2.put("mazi",4);
System.out.println(map2);//{mazi=4}
//void putAll(Map m):将m中的所有键值对存放到当前map中
map1.putAll(map2);
System.out.println(map1);//{mazi=4, lisi=1, zhangsan=2, wanger=3}
//void clear():清空当前map中的所有数据
map2.clear();
System.out.println(map2);//{}
}
}
- 元素查询的操作
- Object get(Object key):获取指定key对应的value
- boolean containsKey(Object key):是否包含指定的key
- boolean containsValue(Object value):是否包含指定的value
- int size():返回Map中键值对的个数
- boolean isEmpty():判断当前Map是否为空
- boolean equals(Object obj):判断当前map和参数对象obj是否相等
import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map map1 = new HashMap();
map1.put("lisi",1);
map1.put("zhangsan",2);
map1.put("wanger",3);
System.out.println(map1);//{lisi=1, zhangsan=2, wanger=3}
Map map2 = new HashMap();
map2.put("mazi",4);
System.out.println(map2);//{mazi=4}
//Object get(Object key):获取指定key对应的value
System.out.println(map1.get("wanger"));//3
//boolean containsKey(Object key):是否包含指定的key
System.out.println(map2.containsKey("zhangsan"));//false
//boolean containsValue(Object value):是否包含指定的value
System.out.println(map2.containsValue(4));//true
//int size():返回Map中键值对的个数
System.out.println(map1.size());//3
//boolean isEmpty():判断当前Map是否为空
System.out.println(map2.isEmpty());//false
//boolean equals(Object obj):判断当前map和参数对象obj是否相等
System.out.println(map1.equals(map2));//false
}
}import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map map1 = new HashMap();
map1.put("lisi",1);
map1.put("zhangsan",2);
map1.put("wanger",3);
System.out.println(map1);//{lisi=1, zhangsan=2, wanger=3}
Map map2 = new HashMap();
map2.put("mazi",4);
System.out.println(map2);//{mazi=4}
//Object get(Object key):获取指定key对应的value
System.out.println(map1.get("wanger"));//3
//boolean containsKey(Object key):是否包含指定的key
System.out.println(map2.containsKey("zhangsan"));//false
//boolean containsValue(Object value):是否包含指定的value
System.out.println(map2.containsValue(4));//true
//int size():返回Map中键值对的个数
System.out.println(map1.size());//3
//boolean isEmpty():判断当前Map是否为空
System.out.println(map2.isEmpty());//false
//boolean equals(Object obj):判断当前map和参数对象obj是否相等
System.out.println(map1.equals(map2));//false
}
}
- 元视图操作的方法
- Set keySet():返回所有的key构成的Set集合
- Collection values:返回所有value构成的Collection集合
- Set entrySet():返回所有的键值对构成的Set集合
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapTest {
public static void main(String[] args) {
Map map1 = new HashMap();
map1.put("lisi",1);
map1.put("zhangsan",2);
map1.put("wanger",3);
System.out.println(map1);//{lisi=1, zhangsan=2, wanger=3}
Map map2 = new HashMap();
map2.put("mazi",4);
System.out.println(map2);//{mazi=4}
//Set keySet():返回所有的key构成的Set集合
Set set1 = map1.keySet();
System.out.println(set1);//[lisi, zhangsan, wanger]
//Collection values:返回所有value构成的Collection集合
Collection values = map1.values();
System.out.println(values);//[1, 2, 3]
//Set entrySet():返回所有的键值对构成的Set集合
Set set2 = map1.entrySet();
System.out.println(set2);//[lisi=1, zhangsan=2, wanger=3]
}
}
7.Cllections工具类
7.1 Cllections工具类的概述
- Collections是一个操作Set,List和Map等集合的工具类
- Collections中提供了一系列静态的方法对集合元素进行排序,查询和修改操作,还提供了对集合对象设置不可变,对集合对象实现同步控制等方法
- 排序操作:(均为static方法)
- reverse(List):反转List中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List集合元素按升序排序
- sort(List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
- swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
import java.util.*;
public class MapTest {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
System.out.println(list);//[1, 2, 3, 4]
//reverse(List):反转List中元素的顺序
Collections.reverse(list);
System.out.println(list);//[4, 3, 2, 1]
//shuffle(List):对List集合元素进行随机排序
Collections.shuffle(list);
System.out.println(list);//[3, 4, 2, 1]
//sort(List):根据元素的自然顺序对指定List集合元素按升序排序
Collections.sort(list);
System.out.println(list);//[1, 2, 3, 4]
//swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
Collections.swap(list,0,3);
System.out.println(list);//[4, 2, 3, 1]
}
}
7.2 Collections常用方法
查找,替换
Object max(Collection):返回给定集合中的最大元素
Object min(Collection):返回给定集合中的最小元素
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List对象的所有旧值
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MapTest {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
List list1 = Arrays.asList(new Object[list.size()]);
System.out.println(list);//[1, 2, 3, 4]
//Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
System.out.println(Collections.max(list));//4
//Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素
System.out.println(Collections.min(list));//1
//int frequency(Collection,Object):返回指定集合中指定元素的出现次数
System.out.println(Collections.frequency(list,1));//1
//void copy(List dest,List src):将src中的内容依次覆盖到dest中
Collections.copy(list1,list);
System.out.println(list1);//[1, 2, 3, 4]
//boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List对象的所有旧值
Collections.replaceAll(list,1,4);
System.out.println(list);//[4, 3, 2, 4]
}
}
7.3 集合的练习实例
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
//练习一
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List list = new ArrayList();
for (int i = 0; i < 10; i++) {
list.add(scanner.nextInt());
}
//自然顺序 从小到大
Collections.sort(list);
//反转元素的顺序变成从大到小
Collections.reverse(list);
System.out.println(list);
}
}
import java.util.*;
//练习二
/*把学生名与考试分数录入到Set中,并按分数显示前三名成绩学员的名字要求用Set实现,定义Student类实现Comparable接口。*/
public class SortStudentScores {
public static void main(String[] args) {
Set<Student> set = new HashSet<>();
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生的姓名和成绩");
String name;
int score;
int i = 1;
int m =1;
/*Student tmp = new Student();放在外面的话,修改tmp会影响到set中的对象*/
while (true) {
Student tmp = new Student();//创建不同的对象;
System.out.print("请输入第" + i + "位学生的姓名:");
name = sc.nextLine();
tmp.setName(name);
System.out.print("请输入第" + i++ + "位学生的成绩:");
score = Integer.parseInt(sc.nextLine());
if (m == 5) break;
tmp.setScore(score);
/*通过变量监视可以发现,通过add添加到set的操作时讲tmp对象的地址存入set,如果这是任然在tmp实例(同一个实例上做值的修改,那么还是还会导致set所指的对象发生变化
* 因此我们需要一个个的创建不同的对象才可以.*/
set.add(tmp);
m++;
}
List<Student> list = new ArrayList<>();
for (Student x : set) {
list.add(x);
}
Collections.sort(list);
System.out.println("您输入的成绩生成成绩单结果:");
for(Student x:list){
System.out.println(x);
}
System.out.println("前三名学生的姓名为:");
Iterator<Student> it=list.iterator();/*不要用new去处理迭代器,list中的iterator方法会返回一个合适的迭代器,而不是人为创建Iterator对象*/
for(int j = 0;j<3&&it.hasNext();j++){
System.out.println(it.next());
}
}
}
class Student implements Comparable<Student> {
String name;
int score;
public void setName(String name) {
this.name = name;
}
public void setScore(int score) {
this.score = score;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return score == student.score &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, score);//注意是.hash而不是hashCode
}
@Override
public int compareTo(Student o) {
return o.score - this.score;
}
@Override
public String toString() {
return name + "--->" + score;
}
}