本章内容
Collection
List接口及其实现类
泛型
Set接口及其实现类
Iterable
Collections
Comparable
Map
hashCode & equals
问题:一个班级有30名学生,在程序中如何保存这些学生的信息呢?
解决方案:可以在班级类中定义一个数组:
Student students[] = new Student[30];
新的问题:
班级需要增加一名新学生,如何保存?
如何对学生按姓名进行排序?
…
Collection
Collection对象是将多个元素组成一个单元的对象
集合用于存储、检索和操纵数据
集合框架的优点:
提供有用的数据结构和算法,从而减少编程工作
高性能的数据结构和算法提高了程序速度和质量
List接口的实现类-ArrayList
ArrayList 对象是长度可变的对象引用数组,类似于动态数组
继承 AbstractList 并实现 List 接口
随着元素的添加,元素的数目会增加,列表也会随着扩展
访问和遍历对象时,它提供更好的性能
ArrayList 类的常用方法:
add(Object e) 为列表增加一个新元素
get(int index) 得到下标为index的元素
remove(int index) 删除下标为index的元素
remove(Obiect e) 删除元素e
size() 获得列表的长度
泛型
泛型的使用:
List students = new ArrayList();
students.add(“abc”);//错误,无法通过编译
students.add(new Student()); //正确
Student stu = students.get(0);//不需要强制类型转换
package test2;
public class Student {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Student(){}
public Student(int id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
//重写toString()
public String toString(){
//System.out.println("id="+id+";name="+name);
return ("id="+id+";name="+name+";password="+password);
}
public Student parseStudent(String str){
Student a=new Student();
String data[]=str.split("[;]");
if(data[0]!=null){
a.id=Integer.parseInt(data[0].substring(data[0].indexOf("=")+1));
}
if(data[1]!=null){
a.name=(data[1].substring(data[1].indexOf("=")+1));
}
if(data[2]!=null){
a.password=(data[2].substring(data[2].indexOf("=")+1));
}
return a;
}
}
package test2;
import java.util.ArrayList;
import java.util.List;
public class JiHe {
public static void main(String[] args) {
List<Student> list=new ArrayList<Student>();
Student user1=new Student(1,"jack","pass");
Student user2=new Student(2,"tom","pass");
list.add(user1);
list.add(user2);
//list.remove(1);
list.remove(user1);
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));//list.get()返回的是一个对象
}
}
}
运行结果:
id=2;name=tom;password=pass
Set接口及其实现类–HashSet
数组、List和Set类型对象遍历方式(for each):
int[] array = new int[]{1, 3, 8};
for(int a: array){ System.out.println(a); }
List list = new ArrayList();
for(Integer i:list){ System.out.println(i); }
Set set = new HashSet();
for(Integer i: set){ System.out.println(i); };
如何去除list中的重复项呢?
结合使用set可以实现这个功能
- Set set = new HashSet(list);//将List类型转化成Set类型
- list = new ArrayList(set);//再将Set类型转化成List类型
打印后面的list会发现顺序与最初不一样,可以使用LinkedHashSet来取代HashSet
List<Student> students = new ArrayList<Student>();
students.add(new Student(“terry”, 10));
students.add(new Student(“lily”, 5));
以下遍历方式:
for(Student stu: students){//…}
相当于:
Iterator<Student> ite = students.iterator();
while(ite.hasNext(){
Student stu = ite.next();
//…
}
package test;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
/*Set<String> set=new HashSet<String>();
set.add("abc");
set.add("efg");
set.add("opg");
set.add("efg");
set.remove("opg");
List<String>list=new ArrayList<String>(set);
set.removeAll(list);
for(String ss:set){
System.out.println(ss);
}
/*Iterator<String> str=list.iterator();//迭代器Iterator
while(str.hasNext()){
System.out.println(str.next());
}*/
List<String> use=new ArrayList<String>();
use.add("aaa");
use.add("bbb");
use.add("aaa");
use.add("ccc");
Set<String> se=new LinkedHashSet<String>(use);//将link转换成Set,因为Set无序,LinkedHashSet可以让其有序输出
// for(String yy:se){
// System.out.println(yy);
// }
for(String yy:se){
System.out.println(yy);
}
//use.removeAll(se);
/*for(String yy:use){
System.out.println(yy);
}*/
}
}
运行结果:
aaa
bbb
ccc
Collections
Collections提供了对集合类的一些常用操作
如:排序,查找等
两种排序方法:
package test;
/*User实现了Comparable<User>接口,在CompareTo方法中与其它User进行比较,哪个User大取决于哪个User的姓名的首字母在前*/
public class User implements Comparable<User>{
private String name;
private double score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public User(String name, double score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "User [name=" + name + ", score=" + score + "]";
}
@Override
public int compareTo(User o) {
/*double a=this.score-o.score;
if(a>0){
return 1;
}
else if(a==0){
return 0;
}
else{
return -1;
}*/
return this.getName().compareToIgnoreCase(o.getName());
}
}
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TestUser {
public static void main(String[] args) {
List<User>list=new ArrayList<User>();
list.add(new User("jack",88.5));
list.add(new User("tom",90.7));
list.add(new User("pary",86.9));
System.out.println("方式一按照姓名排序如下:");
Collections.sort(list);//方式一
for(User str:list){
System.out.println(str);
}
System.out.println("方式二按照成绩排序如下:");
Collections.sort(list,new Comparator<User>(){
public int compare(User o1, User o2) {
//return o1.getName().compareToIgnoreCase(o2.getName()
double a=o1.getScore()-o2.getScore();
if(a>0){
return 1;
}
else if(a==0){
return 0;
}
else{
return -1;
}
}
});//方式二
for(User str:list){
System.out.println(str);
}
}
}
这里写代码片
运行结果:
方式一按照姓名排序如下:
User [name=jack, score=88.5]
User [name=pary, score=86.9]
User [name=tom, score=90.7]
方式二按照成绩排序如下:
User [name=pary, score=86.9]
User [name=jack, score=88.5]
User [name=tom, score=90.7]
Map
以IP地址存取为例,假定我们需要保存1亿个IP地址对应的用户信息,有如下IPInfo类
class IPInfo{
private String ip;
private String userName;
private String phone;
//省略相关的set/get方法
}
方案1:用List进行保存
List<IPInfo> ips = new ArrayList<IPInfo>(100000000);//ips.size()依然为0
//将IPInfo对象加入到列表中,省略。
如果有一个IP为192.168.1.110的用户访问了系统,如何获取对应的IPInfo呢?
for(IPInfo ip: ips){
if(ip.getIP().equals(“192.168.1.110”)){
//得到IPInfo对象
}
}
以上的查询方式确实可以找到我们需要的结果,然而要循环很多次,效率低。
方案二:使用Map
HashMap:
实现了 Map 接口
用于存储键/值映射关系
不能保证其元素的存储顺序
HashMap的遍历
package test3;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Map的三种遍历方式
* @author Administrator
*
*/
public class Demo {
public static void main(String[] args) {
Map<Integer,Student> map=new HashMap<Integer,Student>();
map.put(1,new Student(1,"张飞"));
map.put(2,new Student(2,"孙杨"));
map.put(3,new Student(3,"陈云"));
map.put(4,new Student(4,"李官"));
System.out.println("第一种:通过Map.keySet遍历key和value:");
Set<Integer> set=map.keySet();
for(Integer sc:set){
System.out.println(map.get(sc));
}
System.out.println("第二种:通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<Integer, Student>> it = map.entrySet().iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
System.out.println("第三种:通过Map.entrySet遍历key和value");
for (Map.Entry<Integer,Student> entry : map.entrySet()) {
System.out.println(entry);
}
}
}
运行结果:
第一种:通过Map.keySet遍历key和value:
Student [id=1, name=张飞]
Student [id=2, name=孙杨]
Student [id=3, name=陈云]
Student [id=4, name=李官]
第二种:通过Map.entrySet使用iterator遍历key和value:
1=Student [id=1, name=张飞]
2=Student [id=2, name=孙杨]
3=Student [id=3, name=陈云]
4=Student [id=4, name=李官]
第三种:通过Map.entrySet遍历key和value
1=Student [id=1, name=张飞]
2=Student [id=2, name=孙杨]
3=Student [id=3, name=陈云]
4=Student [id=4, name=李官]
package test;
public class IPInfo {
private String ip;
private String name;
private String phone;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public IPInfo(String ip, String name, String phone) {
super();
this.ip = ip;
this.name = name;
this.phone = phone;
}
@Override
public String toString() {
return "IPInfo [ip=" + ip + ", name=" + name + ", phone=" + phone + "]";
}
}
package test;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class MU {
public static void main(String[] args) {
Map<String,IPInfo> ss=new HashMap<String,IPInfo>(1000);
ss.put("192.168.8.7",new IPInfo("192.168.8.7","jack","190842355"));
ss.put("192.168.8.4",new IPInfo("192.168.8.4","tom","1415645566"));
ss.put("192.168.8.5",new IPInfo("192.168.8.5","mack","141265679"));
System.out.println("请输入要查找的ip:");
String in=new Scanner(System.in).nextLine();
System.out.println(ss.get(in));
}
}
运行结果:
请输入要查找的ip:
192.168.8.4
IPInfo [ip=192.168.8.4, name=tom, phone=1415645566]
//获取HashMap中键所对应的值
package test;
public class A {
private int m=0;
public A(int m){
this.m=m;
}
public int getM(){
return m;
}
@Override
public String toString() {
return "A [m=" + m + "]";
}
}
package test;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class TestA {
public static void main(String[] args) {
Map<String,A> map=new HashMap<String,A>();
int tmp=0;
for(int i=0;i<4;i++){
tmp=(int)(Math.random()*100);
map.put("00"+i,new A(tmp));
}
Set<String>set=map.keySet();//将map中的键Set化,以便遍历
for(String ss:set){
System.out.println(map.get(ss));
A a = (A)map.get(ss);
System.out.println(a.getM());
}
}
}
运行结果:
A [m=15]
15
A [m=53]
53
A [m=40]
40
A [m=20]
20
hashCode & equals
重写A中的hashCode,重新检查前面set的长度
pubilc int hashCode(){
return id;
}
重写A中的equals,重新检查前面set的长度
public boolean equals(Object o){
if(!(o instanceof A)){return false;}
return id == ((A)o).id;
}
将一个新的对象add到HashSet中时,程序将结合hashCode和equals两个方法来判断元素是否重复,如果重复,则用新的对象替代老的对象,若不重复,则将新的对象add到set中。
将一个新的key-value对put到HashMap中时,程序将检测key是否重复,原理同上。
总结:类型转换,list转换为set可以用new LinkedHashSet(list),map转换成set可以用
keySet()和entrySet()。