java collection (二)
1。集合的概念:
(1)现实生活中:很多的事物凑在一起。
(2)数学中的集合:具有共同属性的事物的总体。
(3java 中的集合类: 是一种工具类,就像是容器,存储任意数量的具有共同属性的对象。(集合中只能存放对象类型)
2.集合的作用:
(1)在类的内部,对数据进行组织;
(2)简单而快速的搜索大数量的条目;
(3)有的集合接口(Collection 子接口),提供了一系列排列有序的元素,并且可以在序列中间快速的插入或者删除有关元素;
(4)有的集合接口(map 子接口),提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型。
3.集合与数组的对比———为何选择集合而不是数组:
(1)数组的长度是固定的,集合的长度可变。
(2)数组只能通过下标访问元素,类型固定,而有的集合(map 子接口)可以通过任意类型查找所映射的具体对象。
4.Collection接口,子接口以及实现类
接口不能定义对象,实现类才可以实例化。
例如:
List li2=new ArrayList();
Map <String,String> map2=new HashMap<>();
Set<Integer> set=new HashSet();
4.1Collection 接口
(1)是LIst.Set 和Queue接口的父接口。
(2)定义了可用于操作List.Set和Queue的方法——增删该查
5.List接口
5.1List接口及其实现类——ArrayList
(1)List是元素有序并且可以重复的集合,被称为序列。
(2)List可以精确的控制每一个元素的插入位置或删除某个位置元素。
(3)ArrayLis——数组序列,是List的一个重要实现类。
(4)ArrayList 底层是由数组实现的。
注意:对象存入集合都变成object 类型取出时需要类型转换。
5.2List 增加元素
(1)add:添加一个元素;
例如:
List li= new ArrayList();
public static void addStudent ( List li){
for (int i=0;i<5;i++){
Coure crs=new Coure(i+1,i+"年级语文");
Student stu = new Student (i+1,"小张"+i,crs);
//一条一条的添加
li.add(stu);
}
(2)addAll:将一个集合中的所有元素添加到另一个集合中;
例如:
List li2=new ArrayList();
for (int i=0;i<5;i++){
Coure crs=new Coure(i+6,i+"年级语文");
Student stu = new Student (i+6,"小张"+i,crs);
li2.add(stu);
}
//望集合中添加另一个集合的数据
li.addAll(li2);
5.3 List 获取元素
(1)get 方法: 通过位置获取元素
public static void deleteData(List li){
//移除一个元素
li.remove(0);
li.remove(li.get(0));
//移除一个集合
List li2=new ArrayList();
li2.add(li.get(0));
li2.add(li.get(1));
li2.add(li.get(2));
li.removeAll(li2);
}
5.4 List 遍历元素
(1)for 循环遍历,通过下标取值。
例如:
public static void deleteData(List li){ //移除一个元素 li.remove(0); li.remove(li.get(0)); //移除一个集合 List li2=new ArrayList(); li2.add(li.get(0)); li2.add(li.get(1)); li2.add(li.get(2)); li.removeAll(li2);
(2)for each 遍历(实质上就是迭代器的简写)
例如:
public static void printList2(List li){
System.out.println("================================");
System.out.println("我是通过for each 循环遍历的");
for (Object obj: li){
Student item=(Student ) obj;
System.out.println("学生id:"+item.getId()+",学生姓名:"+item.getName()+",学生课程:"
+item.getCoure().getName());
}
}
(3)迭代器(Iterator):只能用来遍历集合;
例如:
public static void printList3(List li){
System.out.println("================================");
System.out.println("我是通过 iterator 循环遍历的");
Iterator <Object> it=li.iterator();
while(it.hasNext()){
Student item=(Student )it.next() ;
System.out.println("学生id:"+item.getId()+",学生姓名:"+item.getName()+",学生课程:"
+item.getCoure().getName());
}
}
5.5 List 修改元素
set 方法:通过位置修改;
例如:
public static void changeData(List li){
Coure crs= new Coure(12,"11年级语文");
Student stu = new Student (12,"王小花",crs);
li.set(1, stu);
}
5.6 List 删除元素
(1)remove
li.remove(0);//删除li 集合中下标为0的元素
(2)removeAll
li.removeAll(li2); //删除li 集合中 li2集合中的所有元素。
(3)remove 和removeAll 的实例代码:
public static void deleteData(List li){
//移除一个元素
li.remove(0);
li.remove(li.get(0));
//移除一个集合
List li2=new ArrayList();
li2.add(li.get(0));
li2.add(li.get(1));
li2.add(li.get(2)); li.removeAll(li2);
}
(4)关于ArrayList 方法引用代码
package com.j1702.list;
import java.util.*; public class TestList {
public static void main(String[] args) {
/*
* 定义一个 List 集合对象, 用于存放5个学生的信息数据
*/
List li= new ArrayList(); addStudent(li);
changeData(li);
printList(li); //deleteData(li);
// printList1(li);
// printList2(li);
// printList3(li); } //修改list数据
public static void changeData(List li){
Coure crs= new Coure(12,"11年级语文");
Student stu = new Student (12,"王小花",crs);
li.set(1, stu);
}
//删除list 数据
public static void deleteData(List li){
//移除一个元素
li.remove(0);
li.remove(li.get(0));
//移除一个集合
List li2=new ArrayList();
li2.add(li.get(0));
li2.add(li.get(1));
li2.add(li.get(2)); li.removeAll(li2);
//如果新建一个 具有 相同属性的student 对象 ,能够传入移除码?
/**
* 学生id:11,学生姓名:张全蛋,学生课程:11年级语文
*/
Coure crs =new Coure (11,"11年级语文");
Student stu= new Student (11,"张全蛋",crs); li.remove(stu);//删除不掉
} //遍历输出list
public static void printList(List li){
System.out.println("================================");
System.out.println("我是通过for && get 循环遍历的");
for (int i=0;i<li.size();i++){
Student item=(Student )li.get(i);
System.out.println("学生id:"+item.getId()+",学生姓名:"+item.getName()+",学生课程:"
+item.getCoure().getName());
}
} public static void printList1(List li){
System.out.println("================================");
System.out.println("我是通过for && toArray 循环遍历的");
for (int i=0;i<li.size();i++){
Student item=(Student )li.toArray()[i];
System.out.println("学生id:"+item.getId()+",学生姓名:"+item.getName()+",学生课程:"
+item.getCoure().getName());
}
}
public static void printList2(List li){
System.out.println("================================");
System.out.println("我是通过for each 循环遍历的");
for (Object obj: li){
Student item=(Student ) obj;
System.out.println("学生id:"+item.getId()+",学生姓名:"+item.getName()+",学生课程:"
+item.getCoure().getName());
}
} public static void printList3(List li){
System.out.println("================================");
System.out.println("我是通过 iterator 循环遍历的");
Iterator <Object> it=li.iterator();
while(it.hasNext()){
Student item=(Student )it.next() ;
System.out.println("学生id:"+item.getId()+",学生姓名:"+item.getName()+",学生课程:"
+item.getCoure().getName());
}
} //象list 中添加5条数据
public static void addStudent ( List li){
for (int i=0;i<5;i++){
Coure crs=new Coure(i+1,i+"年级语文");
Student stu = new Student (i+1,"小张"+i,crs);
//一条一条的添加
li.add(stu);
}
List li2=new ArrayList();
for (int i=0;i<5;i++){
Coure crs=new Coure(i+6,i+"年级语文");
Student stu = new Student (i+6,"小张"+i,crs);
li2.add(stu); }
//望集合中添加另一个集合的数据
li.addAll(li2);
//向指定的位置添加一条数据
Coure crs= new Coure(11,"11年纪的语文");
Student stu= new Student(11,"张全蛋",crs);
li.add(5,stu);
//如果在末尾位置添加一个字符串会出现什么问题?
//li.add("我是字符串,我想添加到li里面");
//如果在20的位置添加一个数据会出现什么问题?
//li.add(20,stu);
//如果在-1的位置添加一个数据会出现什么问题?
//li.add(-1,stu);
} } // Student 类
package com.j1702.list; public class Student {
private Integer id;//学生id
private String name;//学生姓名
private Coure coure;//学生课程
Student(Integer id,String name,Coure coure){//有参构造方法
this.id=id;
this.name=name;
this.coure=coure;
} public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Coure getCoure() {
return coure;
}
public void setCoure(Coure coure) {
this.coure = coure;
} } // Coure 课程类
package com.j1702.list; public class Coure {
private Integer id;//课程id
private String name;//课程名称 public Coure (Integer id,String name){//有参构造方法
this.id=id;
this.name=name;
}
//getter && setter
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override//自动生成方法 右键 ->source -> hashCode() && equals()
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Coure other = (Coure) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
} }
6. 集合中的泛型:
(1)集合中的元素,可以是任意类型的对象(对象的引用)
如果把某个对象放入集合,则会忽略他的类型。而把他当做Object 处理
(2)泛型则是规定了某个集合只可以存放特定类型的对象
a.会在编译期间进行类型检查
b.可以直接按指定类型获取集合元素。
7.泛型集合中可以放入泛型子类对象实例
(1)泛型集合中的限定类型不能使用基本数据类型。
(2)可以通过使用包装类限定允许存入的基本数据类型。
例如:
List<int> li=new ArrayList<int>();//不可以使用基础类型(类型转换错误)
List<Integer> li=new ArrayList<Integer>();//会自动把int 转换为integer 包装类型
8.set 接口
8.1 Set 接口及其实现类——HashSet
(1)Set 是元素无序(放进去的顺序和输出的顺序不一样)并且不可以重复的集合。
set 中多次添加同一对象,只会保留一个。set 中可以添加null,但是也只能又一个null。
(2)HashSet——哈希集,是Set 的一个重要实现类。
(3)set 代码实例:
package com.j1702.set;
import java.util.*; import com.j1702.list.Coure; public class TestSet { public static void main(String[] args) {
Set<Integer> set2=new HashSet();
set2.add(1);
set2.add(89);
set2.add(23);
set2.add(102);
set2.add(46);
set2.add(21);
set2.add(9);
set2.add(64);
set2.add(null);
set2.add(null);
System.out.println("set 接口 无序不能重复"+"==================");
for( Integer integer: set2){
System.out.println(integer);
} List<Integer> li2=new ArrayList();
li2.add(1);
li2.add(89);
li2.add(23);
li2.add(102);
li2.add(46);
li2.add(21);
li2.add(9);
li2.add(64);
li2.add(null);
li2.add(null);
System.out.println("List 接口 有序(放入顺序) 可以重复"+"==================");
for( Integer integer: set2){
System.out.println(integer);
} //1 创建了一个 set 实例对象
Set<Integer> set=new HashSet();
// 2.添加数据
set.add(1);
set.add(4);
set.add(3);
set.add(2);
set.add(5);
//3.输出
for(Integer integer : set){
System.out.println(integer);
}
testConttains();
} public static void testConttains(){
Set<Coure> set_cr= new HashSet<Coure>();
//创建元素对象
Coure cr1=new Coure (1,"语文");
Coure cr2=new Coure (3,"数学");
Coure cr3=new Coure (2,"外语");
Coure cr4=new Coure (4,"综合");
//添加set
set_cr.add(cr1);
set_cr.add(cr2);
set_cr.add(cr3);
set_cr.add(cr4);
//测试 set 中的contains 方法 // Coure 类中必须要有hashcode()&& equals()方法 判断才为true,否则为false
Coure cr=new Coure (4,"综合");
if(set_cr.contains(cr)){
System.out.println("list 中包含综合课");
}else{
System.out.println("list 中不包含综合课");
} } } // Coure 课程类
package com.j1702.set;
import java.util.*; import com.j1702.list.Coure; public class TestSet { public static void main(String[] args) {
Set<Integer> set2=new HashSet();
set2.add(1);
set2.add(89);
set2.add(23);
set2.add(102);
set2.add(46);
set2.add(21);
set2.add(9);
set2.add(64);
set2.add(null);
set2.add(null);
System.out.println("set 接口 无序不能重复"+"==================");
for( Integer integer: set2){
System.out.println(integer);
} List<Integer> li2=new ArrayList();
li2.add(1);
li2.add(89);
li2.add(23);
li2.add(102);
li2.add(46);
li2.add(21);
li2.add(9);
li2.add(64);
li2.add(null);
li2.add(null);
System.out.println("List 接口 有序(放入顺序) 可以重复"+"==================");
for( Integer integer: set2){
System.out.println(integer);
} //1 创建了一个 set 实例对象
Set<Integer> set=new HashSet();
// 2.添加数据
set.add(1);
set.add(4);
set.add(3);
set.add(2);
set.add(5);
//3.输出
for(Integer integer : set){
System.out.println(integer);
}
testConttains();
} public static void testConttains(){
Set<Coure> set_cr= new HashSet<Coure>();
//创建元素对象
Coure cr1=new Coure (1,"语文");
Coure cr2=new Coure (3,"数学");
Coure cr3=new Coure (2,"外语");
Coure cr4=new Coure (4,"综合");
//添加set
set_cr.add(cr1);
set_cr.add(cr2);
set_cr.add(cr3);
set_cr.add(cr4);
//测试 set 中的contains 方法 // Coure 类中必须要有hashcode()&& equals()方法 判断才为true,否则为false
Coure cr=new Coure (4,"综合");
if(set_cr.contains(cr)){
System.out.println("list 中包含综合课");
}else{
System.out.println("list 中不包含综合课");
} } }
(4) set 和list 的区别
* 1.set 无序(放进去的顺序和输出的顺序不一样),
* 2.list 有序(放进去的顺序和输出的顺序一样)
* 3.set 元素不可以重复,list 可以重复
9. Map 接口
9.1 map 接口
(1)map 提供了一种映射关系,其中的元素是以键值对(key-value)的形式存存储的,能够实现根据key快速查找value。
(2)map 中的键值对以Entry(条目)类型的对象实例形式存在
(3)键(key 值)不可重复,value值可以重复。
(4)每个键最多只能映射到一个值。
9.2 HashMap 类
(1)HashMap 是Map的一个重要实现类,也是最常用的,基于哈希表实现。
(2)HashMap中的Entry 对象是无序排列的
(3) key 值和value 值都可以为null,但是一个HashMap只能有一个key值为null 的映射(key值不可以重复)
9.3HashMap中的增删该查与遍历
package com.j1702.map;
import java.util.*;
import java .util.Map;
import java .util.Map.Entry;
import java.util.Set;
import com.j1702.list.Coure;
public class TestMap {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map <String,String> map=new HashMap<>();
map.put("name", "张三");
map.put("age", "22");
map.put("weight", "40");
map.put("dgree", "本科");
map.put("address", "成都煤炭");
//如何输出map 中的元素?
System.out.println("姓名:"+map.get("name")+"年龄"+map.get("age")+"体重"+map.get("weight")
+"学历:"+map.get("dgree")+",地址:"+map.get("address"));
//如何通过遍历输出 map 中的值
System.out.println("================");
Set <String> keys =map.keySet();
for(String string : keys){
System.out.println(string+":"+map.get(string)+",");
}
//entry 实例遍历
System.out.println("================");
Set<Map.Entry<String, String> > entrys=map.entrySet();
for(Entry<String,String>entry : entrys){
System.out.println(entry.getKey()+":"+entry.getValue()+",");
}
testContains(map);
}
//测试 contains
public static void testContains(Map <String,String> map){
System.out.println("map 中包含 name 这个 key "+map.containsKey("name"));
Map <String,String> map2=new HashMap<>();
System.out.println("map 中 包含 张三 这个值"+map.containsValue("张三"));
System.out.println("请输入名字:");
Scanner scan = new Scanner (System.in);
String str=scan.next();
System.out.println("map 中的包含 张三这个值"+map.containsValue(str));
}
}
9.3我们将这 Object的这两个方法覆盖,以正确比较 Map 对象的等价性。
equals(Object o) |
比较指定对象与此 Map的等价性 |
hashCode() |
返回此 Map的哈希码 |
9.3.1上面两种方法的重写代码如下:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override//自动生成方法 右键 ->source -> hashCode() && equals()
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Coure other = (Coure) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
equals 和 hashcode ()方法在eclipse 中的快捷生成方式为
9.4 hashmap 的常用方法
clear() |
从 Map中删除所有映射 |
remove(Object key) |
从 Map中删除键和关联的值 |
put(Object key, Object value) |
将指定值与指定键相关联 |
clear() |
从 Map中删除所有映射 |
putAll(Map t) |
将指定 Map中的所有映射复制到此 map |
9.5代码实例
1 import java.util.HashSet;
2 import java.util.Set;
3
4 /**
5 * 学生类
6 * @author lenovo
7 *
8 */
9 public class Student {
10
11 public String id;
12
13 public String name;
14
15 public Set<KeCheng> kecheng;
16
17 public Student(String id,String name){
18 this.id = id;
19 this.name = name;
20 this.kecheng = new HashSet<KeCheng>();
21 }
22
23 }
然后再创建一个MapTest的测试类,演示Map的使用方法,并且创建一个演示put()方法和keySet()方法的成员方法
1 import java.util.HashMap;
2 import java.util.Map;
3 import java.util.Scanner;
4 import java.util.Set;
5
6 public class MapTest {
7
8 //创建一个Map属性用来承装学生对象
9 public Map<String,Student> student;
10
11 /*
12 * 在构造器中初始化学生属性
13 */
14 public MapTest(){
15 this.student = new HashMap<String,Student>();
16 }
17
18 /*
19 * 添加方法:输入学生ID,判断是否被占用,
20 * 如果未被占用,则输入姓名,创建新学生对象,添加到student中
21 */
22 public void testPut(){
23 //创建一个Scanner对象,输入学生ID
24 Scanner sc = new Scanner(System.in);
25 int i = 0;
26 while(i<3){
27 System.out.println("请输入学生ID:");
28 String stuID = sc.next();
29 Student stu = student.get(stuID);
30 if(stu == null){
31 System.out.println("请输入学生姓名:");
32 String stuName = sc.next();
33 Student newStudent = new Student(stuID,stuName);
34 student.put(stuID, newStudent);
35 System.out.println("成功添加学生:"+student.get(stuID).name);
36 i++;
37 }else{
38 System.out.println("该学生ID已被占用!");
39 continue;
40 }
41
42 }
43 }
44
45 /*
46 * 测试Map的keySet方法
47 */
48 public void testKeySet(){
49 //通过keySet方法,返回Map中所有“键”的Set集合
50 Set<String> keySet = student.keySet();
51 //取得student的容量
52 System.out.println("总共有"+student.size()+"个学生;");
53 //遍历keySet,取得每一个键,再调用get方法取得每个键对应的value
54 for (String stuID : keySet) {
55 Student stu = student.get(stuID);
56 if(stu != null){
57 System.out.println("学生:"+stu.name);
58 }
59 }
60 }
61
62 public static void main(String[] args) {
63
64 MapTest mt = new MapTest();
65 mt.testPut();
66 mt.testKeySet();
67 }
68
69 }
运行main方法后的结果如下:
请输入学生ID:
1
请输入学生姓名:
Tom
成功添加学生:Tom
请输入学生ID:
2
请输入学生姓名:
Jack
成功添加学生:Jack
请输入学生ID:
3
请输入学生姓名:
Lily
成功添加学生:Lily
总共有3个学生;
学生:Tom
学生:Jack
学生:Lily
使用Map中的remove()方法删除Map中的映射
1 /*
2 * 删除Map中的映射
3 */
4 public void testRemove(){
5 Scanner sc = new Scanner(System.in);
6 while(true){
7 System.out.println("请输入要删除的学生ID:");
8 String stuID = sc.next();
9 //判断输入的ID是否存在对应的学生对象
10 Student stu = student.get(stuID);
11 if(stu == null){
12 System.out.println("输入的学生ID不存在!");
13 continue;
14 }
15 student.remove(stuID);
16 System.out.println("成功删除学生"+stu.name);
17 break;
18 }
19 testEntrySet();
20 }
使用entrySet()方法遍历Map
1 /*
2 * 通过entrySet来遍历Map
3 */
4 public void testEntrySet(){
5 //通过entrySet返回Map中所有的键值对
6 Set<Entry<String,Student>> entrySet = student.entrySet();
7 for(Entry<String,Student> entry:entrySet){
8 System.out.println("取得键:"+entry.getKey());
9 System.out.println("对应的值为:"+entry.getValue().name);
10 }
11 }
使用put()方法来修改Map中已存在的映射
1 /*
2 * 使用put方法修改Map中已有的映射
3 */
4 public void testModify(){
5 System.out.println("请输入要修改的学生ID:");
6 Scanner sc = new Scanner(System.in);
7 while(true){
8 String id = sc.next();
9 Student stu = student.get(id);
10 if(stu == null){
11 System.out.println("ID不存在!");
12 continue;
13 }
14 System.out.println("当前学生是:"+stu.name);
15 System.out.println("请输入新的学生:");
16 String name = sc.next();
17 Student newStu = new Student(id,name);
18 student.put(id, newStu);
19 System.out.println("修改成功!");
20 break;
21 }
22 }
使用Map中的containsKey()和containsValue()方法来判断Map中是否存在键或值
1 /*
2 * 测试Map中是否存在某个key值或value值
3 */
4 public void testContainsKey(){
5 System.out.println("请输入学生ID:");
6 Scanner sc = new Scanner(System.in);
7 String stuID = sc.next();
8 //用containsKey()方法来判断是否存在某个key值
9 System.out.println("输入的ID为:"+stuID+",在学生列表中是否存在:"+student.containsKey(stuID));
10 if(student.containsKey(stuID)){
11 System.out.println("学生的姓名为:"+student.get(stuID).name);
12 }
13
14 System.out.println("请输入学生姓名:");
15 String name = sc.next();
16 //用containsValue()方法来判断是否存在某个value值
17 if(student.containsValue(new Student(null,name))){
18 System.out.println("存在学生"+name);
19 }else{
20 System.out.println("学生不存在");
21 }
22 }
使用containsKey()和containsValue()方法判断是,先在学生类里重写equals()和hashCode()方法,如果只判断值的话,equals方法里只重写和值相关的内容。
10.collection 排序
package com.j1702.sort;
public class Student implements Comparable<Student> {
private Integer id;
private String name;
private Integer age;
public Student(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
//根据id 排序
@Override
public int compareTo(Student o) {
if(this.id > o.id){
return 1;
} else if(this.id<o.id){
return -1;
}else{
return 0;
}
}
//根据汉子子hashmap中的顺序排序
//@Override
// public int compareTo(Student o) {
// if (this.name.compareTo(o.name)>0) {
// return 1;
// } else if (this.name.compareTo(o.name)<0) {
// return -1;
// } else {
// return 0;
//
// }
// }
}
package com.j1702.sort;
import java.util.*;
public class Student_sort {
public static void main(String[] args) {
Student stu1 = new Student(1001, "张三", 25);
Student stu2 = new Student(1004, "李四", 26);
Student stu3 = new Student(1007, "王五", 20);
Student stu4 = new Student(1002, "小红", 18);
Student stu5 = new Student(1005, "旺财", 17);
List<Student> li = new ArrayList<Student>();
li.add(stu1);
li.add(stu2);
li.add(stu3);
li.add(stu4);
li.add(stu5);
Collections.sort(li);
for(Student s:li){
System.out.println(s.getName() + " " + s.getAge() + " " + s.getId() );
}
}
}
注意;根据name字段排名时,中文 的顺序不是按照字母来排序的,他是通过汉字在hash码的大小来排序的。如果要实现中文根据拼音来排序,下载中文架包。
com.ibm.icu_3.8.jar
11.comparable 和comparator 的区别
11.1Comparable 简介
Comparable 是排序接口。
若一个类实现了Comparable接口,就意味着“该类支持排序”。 即然实现Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。
此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。
11.2Comparable 定义
Comparable 接口仅仅只包括一个函数,它的定义如下:
package java.lang;
import java.util.*; public interface Comparable<T> {
public int compareTo(T o);
}
说明:
假设我们通过 x.compareTo(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。
11.3Comparator 简介
Comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现Comparator接口即可。
也就是说,我们可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
11.4Comparator 定义
Comparator 接口仅仅只包括两个个函数,它的定义如下:
package java.util; public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj);
}
说明:
(01) 若一个类要实现Comparator接口:它一定要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) 函数呢? 因为任何类,默认都是已经实现了equals(Object obj)的。 Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数;所以,其它所有的类也相当于都实现了该函数。
(02) int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
11.5 Comparator 与 Comparable 相同点
Comparable & Comparator 都是用来实现集合中元素的比较、排序的;
Comparable & Comparator 均为 Java 接口,Comparable 位于包 java.lang 下,而 Comparator 位于包 java.util 下;
自定义类实现二者中的一个,便可进行比较大小。
11.6.Comparator 与 Comparable 不同点
Comparable 一般定义在类的内部,而Comparator 一般定义在类的外部;
实现 Comparable 接口需要重写其 compareTo 方法,而实现 Comparator 接口需要重写其 compare 方法
11.7 代码实例
(1)Comparable
package test; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; public class test {
public static void main(String[] args) {
List<UserInfo> list = new ArrayList<UserInfo>();
list.add(new UserInfo(1,21,"name1"));
list.add(new UserInfo(2,27,"name1"));
list.add(new UserInfo(3,15,"name1"));
list.add(new UserInfo(5,24,"name1"));
list.add(new UserInfo(4,24,"name1"));
//对该类排序
Collections.sort(list);
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
} class UserInfo implements Comparable<UserInfo>{
private int userid;
private int age;
private String name;
public UserInfo(int userid, int age, String name) {
this.userid = userid;
this.age = age;
this.name = name;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return this.userid+","+this.age+","+this.name;
}
@Override
public int compareTo(UserInfo o) {
//如果年龄相同,则比较userid,也可以直接 return this.age-o.age;
if(this.age-o.age==0){
return this.userid-o.userid;
}else{
return this.age-o.age;
}
} }
(2)comparator
package test; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; public class test1 {
public static void main(String[] args) {
List<UserInfo> list = new ArrayList<UserInfo>();
list.add(new UserInfo(1,21,"name1"));
list.add(new UserInfo(2,27,"name2"));
list.add(new UserInfo(3,15,"name3"));
list.add(new UserInfo(5,24,"name4"));
list.add(new UserInfo(4,24,"name5"));
//new一个比较器
MyComparator comparator = new MyComparator();
//对list排序
Collections.sort(list,comparator);
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}
class MyComparator implements Comparator<UserInfo>{
@Override
public int compare(UserInfo o1,UserInfo o2) { if(o1.getAge()-o2.getAge()==0){
return o1.getUserid()-o2.getUserid();
}else{
return o1.getAge()-o2.getAge();
}
}
}
class UserInfo{
private int userid;
private int age;
private String name;
public UserInfo(int userid, int age, String name) {
this.userid = userid;
this.age = age;
this.name = name;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return this.userid+","+this.age+","+this.name;
}
}
(3总结;
使用 Comparable 较为简单, 只要实现 Comparable 接口的对象就直接成为一个可以比较的对象,但是 需要修改源代码,而且由于这样做会导致代码耦合性比较高,会严重影响到代码的可扩展性;
用 Comparator 的好处是 不需要修改源代码,不会使代码发生强耦合 , 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时,把比较器和对象一起传递过去就可以比大小 ;
所以,就代码可扩展性角度而言,使用实现 Comparator 接口的方式去实现容器内元素的排序会更好一些。
java collection (二)的更多相关文章
- Java Collection Framework : List
摘要: List 是 Java Collection Framework的重要成员,详细包括List接口及其全部的实现类.由于List接口继承了Collection接口,所以List拥有Collect ...
- Java面试题总结之Java基础(二)
Java面试题总结之Java基础(二) 1.写clone()方法时,通常都有一行代码,是什么? 答:super.clone(),他负责产生正确大小的空间,并逐位复制. 2.GC 是什么? 为什么要有G ...
- Java Collection开发技巧
Java Collection(集合) 集合中的一些技巧: 通过Collections类的静态方法,可以对集合进行一些操作 1 java.util.List<Integer> number ...
- Java EE : 二、图解 Cookie(小甜饼)
目录 Java EE : 一.图解Http协议 Java EE : 二.图解 Cookie(小甜饼) Java EE : 三.图解Session(会话) 概述 一.概述 二.详细介绍Cookie 传输 ...
- 利用JAVA生成二维码
本文章整理于慕课网的学习视频<JAVA生成二维码>,如果想看视频内容请移步慕课网. 维基百科上对于二维码的解释. 二维条码是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图 ...
- Java Collection Framework概述
文章出自:听云博客 Collection概述 Java collection是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映射等. Java集合主要可以划分为4个部分:Li ...
- Java Collection好文章
Java Collection好文章 http://my.oschina.net/xiaomaoandhong/blog/78394
- java实现二维码
说起二维码,微信好像最先启用,随后各类二维码就开始流行起来了.那什么是二维码呢. 1.什么是二维码?百度一下即可 http://baike.baidu.com/view/132241.htm?fr=a ...
- java collection framework
java collection framework Map
- Java Collection 集合类大小调整带来的性能消耗
Java Collection类的某些详细实现因为底层数据存储基于数组,随着元素数量的添加,调整大小的代价非常大.随着Collection元素增长到某个上限,调整其大小可能出现性能问题. 当Colle ...
随机推荐
- 20172330 2017-2018-1 《Java程序设计》第四周学习总结
20172330 2017-2018-1 <Java程序设计>第四周学习总结 教材学习内容总结 这一周的内容还是比较多的,而且很复杂,包含第四和第七章. 第四章向我们介绍了类结构的定义与概 ...
- iOS-开发过程中应用间跳转问题
- 转 高性能IO模型浅析
高性能IO模型浅析 转自:http://www.cnblogs.com/fanzhidongyzby/p/4098546.html 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: ( ...
- ubuntu 安装lua错误
转自:http://www.cnblogs.com/softidea/archive/2016/03/02/5236498.html lua.c:80:31: fatal error: readlin ...
- 用c++读取文件夹中的所有文件名
//头文件,注意要加stdafx.h和io.h等 #include "stdafx.h" #include <io.h> #include <vector> ...
- 如何高效的使用Google
文章再转自知乎:http://www.zhihu.com/question/20161362
- array to object
array to object native js & ES6 https://stackoverflow.com/questions/4215737/convert-array-to-obj ...
- Django+haystack实现全文搜索出现错误 ImportError: cannot import name signals
原因是在你的settings.py或者其他地方使用了 "import haystack" 当我们使用django-haysatck库时,表面上会有haystack库,但实际上并不 ...
- java 注解使用笔记
一.语法 注解也属于一种类型 public @interface MyTestAnnotation { } 用@interface描述 根据情况可以应用于包.类型.构造方法.方法.成员变量.参数及本地 ...
- [luogu5176] 公约数
题目描述 求 \[ \sum_{i=1}^n\sum_{j=1}^m\sum_{k=1}^p\gcd(i\cdot j,i\cdot k,j\cdot k)\times \gcd(i,j,k)\tim ...