集合map、泛型

来源:互联网 发布:javascript获取日期 编辑:程序博客网 时间:2024/06/04 23:26

1. 集合

1.1. Map

什么是Map?

Map 是映射接口,Map中存储的内容是键值对(key-value)。

Map映射中不能包含重复的键;每个键最多只能映射到一个值。值允许重复。

Map接口提供三种查看方式,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。

Map 映射顺序。TreeMap有序,HashMap无序。

什么是键值对?(key-value)

键:就是你存的值的编号

值:就是你要存放的数据

1.2. HashMapAPI

HashMap的常见用法:可举例(学号加姓名)

/**

 * hashMap的常见用法

 * 键不能重复,值可以重复

 * 无序

 * @author Administrator

 *

 */

public class TestMap01 {

public static void main(String[] args) {

//Map map = new HashMap();

HashMap<Integer,String> map = new HashMap<Integer,String>();

//-

map.put(101, "jack");

map.put(102, "tom");

map.put(103, "bob");

map.put(104, "jack");

map.put(103, "kate");

//判断是否包含某个键

System.out.println("是否包含键‘103’"+map.containsKey(103));

//判断是否包含某个值

System.out.println("是否包含值‘jack':"+map.containsValue("jack"));

//查看集合的元素个数

System.out.println("集合中的元素个数:"+map.size());

//根据键取值

System.out.println("‘103’这个键对应的值为:"+map.get(103));

System.out.println("------遍历1根据键获取值-----");

searchKeys(map);

System.out.println("------遍历2-值集获取的对应的键-值对的集合-----");

searchEntry(map);

System.out.println("------遍历3直接获取值集----");

searchValues(map);

}

1.3. HashMap遍历的三种方式

1.直接获取键值对

2.根据键取值

3.直接得到值的集合

/**

 * 方式1根据键-获取值 ,最常用的

 */

public static void searchKeys(HashMap<Integer,String> map){

//获取所有的键对应的集合

Set<Integer> keys = map.keySet();

//遍历键集,根据键获取值

//获取迭代器对象

Iterator<Integer> it = keys.iterator();

while(it.hasNext()){

//获取的键

Integer key = it.next();

//根据键获取值

String value = map.get(key);

System.out.println("[键:"+key+",值:"+value+"]");

}

}

/**

 * 方式2:获取的就是键-值对对应的集合最好

 * @param map

 */

public static void searchEntry(HashMap<Integer,String> map){

//Map.Entry(键,值)接口 看成是一种类型,该类型带了2个参数,set集合中的每一个元素都是实现了Map.Entry()接口的这种类型的元素 ,元素格式  "="

Set<Map.Entry<Integer, String>> set = map.entrySet();

//获取迭代器

Iterator<Map.Entry<Integer, String>> it = set.iterator();

while(it.hasNext()){

Map.Entry<Integer,String> en = it.next();

//System.out.println("****"+en);

//获取键

Integer key = en.getKey();

//获取值

String value = en.getValue();

System.out.println("[键:"+key+",值:"+value+"]");

}

}

/**

 * 方式3:直接获取值集

 * @param map

 */

public static void searchValues(HashMap<Integer,String>map){

//Collection

Collection<String> col = map.values();

//获取迭代器对象

Iterator<String> it = col.iterator();

while(it.hasNext()){

String value = it.next();

System.out.println("值:"+value);

}

}

1.4. 泛型

什么是泛型?

JDK5引入泛型。

目的一是解决集合使用过程中的运行时类型错误,约束自己的编码。在代码中定义的List<Integer>和List<String>等类型,在编译之后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。这个过程就称为类型擦除。

目的二是对类型系统的扩展,支持创建可以按类型进行参数化的类。

泛型的作用?

Map m = new HashMap();

m.put("S001", "小明");

String s = (String) m.get("S001");

System.out.println(s);

因为 Map.get() 被定义为返回 Object,所以一般必须将 Map.get() 的结果强制类型转换为想要的类型如String,如将 get() 的结果强制类型转换为 String,并且希望结果真的是一个 String。但是有可能在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。

我们想要

如果能规定里面储存的对象类型,防止将错误类型的键或值保存在集合中,就不会存在潜在的异常风险。

泛型的好处:方便、安全

举例子:用泛型,不用泛型

Map m = new HashMap();

m.put("S001", "小明");

m.put("s102", "张三");

m.put("S003", new Dog("旺财","吉娃娃"));

// String s = (String) m.get("S001");

//java.lang.ClassCastException S003该键对应的值是1Dog对象,而我们把它强转成1String对象

String s =(String)m.get("S003");

System.out.println(s);

练习

Map m = new HashMap();

m.put("S001", "小明");

String s = (String) m.get("S001");

System.out.println(s);

该代码改为泛型,确保put只能添加String而不能添加Book类,输出时不用做强制转换。

1.5. 开发自己的泛型类

观察JDK中Map接口如何定义

public interface Map<K, V> {

public void put(K key, V value);

public V get(K key);

}

注意该接口在类的声明中使用K和V,表示在声明一个 Map 类型的变量时指定的类型的占位符。在 get()、put() 和其他方法的方法声明中使用的 K 和 V。所以我们才可以这样用:

Map<String, String> m = new HashMap<String, String>();

m.put("S001", "小明");

String s = m.get("S001");

命名类型参数

K —— 键,比如映射的键。

V —— 值,比如 List 和 Set 的内容,或者 Map 中的值。

E —— 异常类。

T —— 泛型。

模仿Map接口开发自己的泛型类

(1) 存放个人信息(性别表述方式变化)

分析: String  sex  ,“男”,”女” char  字符类型 ‘男’,’女’, int  整数类型  1:男   0:女

public class Person<T> {

private String name;

private T sex;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public T getSex() {

return sex;

}

public void setSex(T sex) {

this.sex = sex;

}

public Person(String name, T sex) {

super();

this.name = name;

this.sex = sex;

}

public Person() {

}

@Override

public String toString() {

return "姓名:"+this.name+",性别:"+this.sex;

}

}

public class TestPerson {

public static void main(String[] args) {

//性别String

Person<String> p1 = new Person<String>();

p1.setName("张三");

p1.setSex("");

System.out.println(p1.toString());

//char字符

Person<Character> p2 = new Person<Character>();

p2.setName("李四");

p2.setSex('');

System.out.println(p2.toString());

//int类型

Person<Integer> p3 = new Person<Integer>();

p3.setName("王五");

p3.setSex(1);

System.out.println(p3.toString());

}

}

(2) 存放商品信息(商品价格从int变为double)

分析: 商品 2个属性   商品名  ,商品价格 Goods<T>

(3) 设置点的坐标(x,y)(可以为整型,可以为浮点型,可以为String)

分析: int,double,String  类 Point<K,T>  

1.6. 类型通配符

public static void main(String args[]) {

List<Integer> list = new ArrayList<Integer>();

list.add(1);

printList(list);

}

public static void printList(List list) {

for (Object o : list)

System.out.println(o);

}

如果试图用 List<Integer> 调用printList,会得到警告。

如果改为List<Object>还是会出错

解决方案是使用通配符

上面代码中的问号是一个类型通配符。List<?> 是任何泛型 List 的父类型,所以可以将 List<Object>、List<Integer>传递给 printList()。

例题:

public class TestArrayList02 {

public static void main(String[] args) {

List<Integer> list = new ArrayList<Integer>();

list.add(1);

list.add(2);

list.add(30);

printList(list);

System.out.println("-------------------------");

List<String> list2 = new ArrayList<String>();

list2.add("tom");

list2.add("jack");

list2.add("bob");

printList(list2);

System.out.println("-------------------------");

List<Double> list3 = new ArrayList<Double>();

list3.add(12.33);

list3.add(21.33);

printList(list3);

}

/**

 * 遍历List集合

 * @param list

 */

public static void printList(List<?> list) {

for (Object o : list)

System.out.println(o);

}

}

1.7. 类型系统的两个维度

引入泛型之后的类型系统增加了两个维度:一个是类型参数自身的继承体系结构,另外一个是泛型类或接口自身的继承体系结构。

当泛型类的类型声明中使用了通配符的时候, 其子类型可以在两个维度上分别展开:

在List维度展开

List<String> list;

ArrayList<String>;

在类型维度展开

List<String> list;

List<?> list2;

1.8. Properties使用

什么是配置文件?

配置文件中很多变量经常改变,如果配置经常改变,而不希望修改代码,可以把配置保存在单独的文件中,让用户能够脱离程序去修改相关的配置。

Properties的作用?

读取Java的配置文件

步骤:1.在src下创建XXX.proterties ( 选中src,右击 ---new---file--输入文件名 XXX.properties)

2. 新建Properties对象 ,通过load(),将配置文件信息加载进内存,读取保存到p变量中

3. 配置文件的信息已经读取保存在p变量里了,要获取对应的迭代器对象 ,遍历,读出内容

/**

 * src下的配置文件config.properties中的内容读取出来,输出在控制台

 * load(InputStream ins)

 * @author Administrator

 *

 */

public class TestProperties {

public static void main(String[] args) {

//2.新建properties对象,通过p.load()方法,加载进内存

Properties p = new Properties();

try {

//先获取类对象,然后拿到类加载器,加载配置文件

p.load(TestProperties.class.getClassLoader().getResourceAsStream("config.properties"));

/*//获取类对象

Class cla = TestProperties.class;

//获取输入流对象

InputStream ins = cla.getClassLoader().getResourceAsStream("config.properties");

//加载输入流对象

p.load(ins);*/

//3.配置文件的信息已经读取保存在p变量里了,要获取对应的迭代器对象 ,遍历,读出内容

Enumeration<String> en = (Enumeration<String>)p.propertyNames();

while(en.hasMoreElements()){

//System.out.println(en.nextElement());

//获取键

String key = en.nextElement();

//获取值

String value = p.getProperty(key);

System.out.println("="+key+",="+value);

}

} catch (IOException e) {

e.printStackTrace();

System.out.println("加载配置文件出错,出错信息:"+e.getMessage());

}catch (NullPointerException e) {

e.printStackTrace();

System.out.println("出错信息:"+e.getMessage());

}

}

}

3.1. 比较接口,比较器

学号  姓名分数

1 “张三” 89

2 “李四” 78

3  “tom” 98

4  “bob”  45

5  “helen” 78

6   “李四” 78

需求1: 先按分数升序排列,如果分数相同,按学号升序排列

需求2:先按分数降序排列,如果分数相同,按姓名升序排列,如果姓名相同,按学号降序排列

需求3:先按姓名降序排列,姓名相同,按学号升序

新闻标题类 NewsItem   新闻编号int  Id  ,新闻标题String title   ,新闻的出版时间java.util.Date, publishDate   

需求: 先按出版时间升序排列,如果出版时间相同,按标题的降序排列,如果标题相同,按新闻编号的升序排列  

编号   标题    出版时间

101   财经    ‘2014-5-6’

103   体育     ‘2012-5-6’

109   娱乐     ‘2016-7-8’

105   篮球      ‘2015-6-7’

108    足球      ‘2017-3-2’

分析: 1条数据 看成1个Student对象 ,Student类 ,3个属性 学号  stuNo int  ,姓名name String,分数 score int

6个对象 ,存储到哪里呢? 思路1 存储到集合中(方便)  List<Student> list = new ArrayList<Student>();  思路2: 存储到对象数组中 Student[] stuArr = new Student[10];

方式1:  1. 要排序的类Student类 实现比较接口   implements Comparable接口 ,重写 compareTo比较方法(比较的规则要和需求一致)  

2.测试类中,集合中添加数据 ,对集合对象List排序 ,借助工具类Collections.sort(list)   ,测试类中,对象数组中添加数据,对对象数组排序  ,借助工具类 Arrays.sort(stuArr)  

package com.compareabletest;

public class Studentimplements Comparable<Student> {

private int stuNo;//学号

private String name; //姓名

private int score;//成绩

public Student() {

}

public Student(int stuNo, String name,int score) {

super();

this.stuNo = stuNo;

this.name = name;

this.score = score;

}

 

public String getName() {

return name;

}

public int getScore() {

return score;

}

public int getStuNo() {

return stuNo;

}

public void setName(String name) {

this.name = name;

}

public void setScore(int score) {

this.score = score;

}

public void setStuNo(int stuNo) {

this.stuNo = stuNo;

}

 

/**

 * 需求1: 先按分数升序排列,如果分数相同,按学号升序排列

 */

/*@Override

public int compareTo(Student o) {

int result = this.score-o.score; //分数的升序

if(result==0){ //分数相同

result = this.stuNo-o.stuNo; //学号的升序

}

return result;

}*/

/**

 * 需求2:先按分数降序排列,如果分数相同,按姓名升序排列,如果姓名相同,按学号降序排列

 */

/*@Override

public int compareTo(Student o) {

int result = -(this.score-o.score); //分数的降序

if(result==0){ //分数相同

result = this.name.compareTo(o.name); //姓名的升序

if(result==0){ //姓名相同

result= -(this.stuNo-o.stuNo);

}

}

return result;

}*/

/**

 * 需求3:先按姓名降序排列,姓名相同,按学号升序

 */

@Override

public int compareTo(Student o) {

int result =-this.name.compareTo(o.name);//姓名的降序

if(result==0){ //姓名相同

result = this.stuNo-o.stuNo;  //学号升序

}

return result;

}

@Override

public String toString() {

return this.getStuNo()+"\t"+this.getName()+"\t"+this.getScore();

}

}

package com.njwb.compareabletest;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class TestStudent01 {

public static void main(String[] args) {

List<Student> list = new ArrayList<Student>();

list.add(new Student(6,"李四",78));

list.add(new Student(1,"张三",89));

list.add(new Student(2,"李四",78));

list.add(new Student(3,"tom",98));

list.add(new Student(4,"bob",45));

list.add(new Student(5,"helen",78));

System.out.println("排序前:");

for(Student s:list){

System.out.println(s);

}

//调用排序

Collections.sort(list);

System.out.println("排序后:");

for(Student s:list){

System.out.println(s);

}

}

}

package com.njwb.compareabletest;

import java.util.Arrays;

public class TestStudent02 {

public static void main(String[] args) {

Student[] stuArr = new Student[6];

stuArr[0] = new Student(6,"李四",78);

stuArr[1] = new Student(1,"张三",89);

stuArr[2] = new Student(2,"李四",78);

stuArr[3] = new Student(3,"tom",98);

stuArr[4] = new Student(4,"bob",45);

stuArr[5] = new Student(5,"helen",78);

System.out.println("排序前:");

for(Student s:stuArr){

System.out.println(s);

}

//调用排序

Arrays.sort(stuArr);

System.out.println("排序后:");

for(Student s:stuArr){

System.out.println(s);

}

}

}

package com.njwb.compareabletest;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

/**

 * binarySearch(集合对象,要查找的元素对象)  该方法必须排序后才有效,如果在排序前调用,结果可能不正确

 * max 一般是排序后的末尾元素

 * min  一般是排序后的首个元素

 * reverse 反转  ,排序后集合元素反转

 * @author Administrator

 *

 */

public class TestStudent03 {

public static void main(String[] args) {

List<Student> list = new ArrayList<Student>();

Student stu1 = new Student(6,"李四",78);

Student stu2 = new Student(1,"张三",89);

Student stu3 = new Student(2,"李四",78);

Student stu4 = new Student(3,"tom",98);

Student stu5 = new Student(4,"bob",45);

Student stu6 = new Student(5,"helen",78);

list.add(stu1);

list.add(stu2);

list.add(stu3);

list.add(stu4);

list.add(stu5);

list.add(stu6);

System.out.println("排序前:");

for(Student s:list){

System.out.println(s);

}

//判断某一个元素的索引位置  ,比方说stu1李四所在的索引位置  结果是-4,为什么不是0,因为该方法必须在排序后才有效

System.out.println("排序前stu1所在的索引位置:"+Collections.binarySearch(list, stu1));

//调用排序

Collections.sort(list);

System.out.println("排序后:");

for(Student s:list){

System.out.println(s);

}

//集合中的最大值 默认是排序后的最后一个元素

System.out.println("最大值:\n"+Collections.max(list));

//集合中的最小值 默认是排序后的第一个元素

System.out.println("最小值:\n"+Collections.min(list));

//判断某一个元素的索引位置  ,比方说stu4 tom所在的索引位置

System.out.println("排序后stu4所在的索引位置:"+Collections.binarySearch(list, stu4));

//集合元素的反转  

Collections.reverse(list);

System.out.println("反转后:");

for(Student s:list){

System.out.println(s);

}

}

}

方式2:

1. 新建Student类  2.新建比较器类 StudentComparator ,比较器类实现Comparator接口(java.util.Comparator),重写比较方法int compare(Student o1, Student o2)

2. 测试类和之前的相同  新建集合对象,存储数据 ,通过Collections工具类调用比较方法

public class Student {

private int stuNo;//学号

private String name; //姓名

private int score;//成绩

public Student() {

}

public Student(int stuNo, String name,int score) {

super();

this.stuNo =stuNo;

this.name = name;

this.score = score;

}

 

public String getName() {

return name;

}

public int getScore() {

return score;

}

public int getStuNo() {

return stuNo;

}

public void setName(String name) {

this.name = name;

}

public void setScore(int score) {

this.score = score;

}

public void setStuNo(int stuNo) {

this.stuNo = stuNo;

}

 

@Override

public String toString() {

return this.getStuNo()+"\t"+this.getName()+"\t"+this.getScore();

}

}

package com.njwb.comparatoruse;

import java.util.Comparator;

public class StudentComparatorimplements Comparator<Student> {

/**

 * 需求1: 先按分数升序排列,如果分数相同,按学号升序排列

 */

/*@Override

public int compare(Student o1, Student o2) {

int result = o1.getScore()-o2.getScore(); //分数升序

if(result==0){ //分数相同

result=o1.getStuNo()-o2.getStuNo(); //学号升序

}

return result;

}*/

/**

 * 需求2:先按分数降序排列,如果分数相同,按姓名升序排列,如果姓名相同,按学号降序排列

 */

/*@Override

public int compare(Student o1, Student o2) {

int result = -(o1.getScore()-o2.getScore()); //分数降序

if(result==0){ //分数相同

result = o1.getName().compareTo(o2.getName()); //姓名的升序

if(result==0){ //姓名相同

result = -(o1.getStuNo()-o2.getStuNo()); //学号降序

}

}

return result;

}*/

/**

 * 需求3:先按姓名降序排列,姓名相同,按学号升序

 */

@Override

public int compare(Student o1, Student o2) {

int result = -o1.getName().compareTo(o2.getName());//姓名降序

if(result==0){ //姓名相同

result = o1.getStuNo()-o2.getStuNo(); //学号升序

}

return result;

}

/**

 * 需求3:先按姓名降序排列,姓名相同,按学号升序

 */

/*@Override

public int compare(Student o1, Student o2) {

if(o1.getName().compareTo(o2.getName())>0){

return -1;      //降序

}else if(o1.getName().compareTo(o2.getName())<0){

return 1;

}else{

if(o1.getStuNo()-o2.getStuNo()>0){

return 1; //学号升序

}else if(o1.getStuNo()-o2.getStuNo()<0){

return -1;

}else{

return 0;

}

}

}*/

}

package com.njwb.comparatoruse;

 

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

 

public class TestStudent01 {

public static void main(String[] args) {

List<Student> list = new ArrayList<Student>();

list.add(new Student(6,"李四",78));

list.add(new Student(1,"张三",89));

list.add(new Student(2,"李四",78));

list.add(new Student(3,"tom",98));

list.add(new Student(4,"bob",45));

list.add(new Student(5,"helen",78));

System.out.println("排序前:");

for(Student s:list){

System.out.println(s);

}

//调用排序

Collections.sort(list, new StudentComparator());

System.out.println("排序后:");

for(Student s:list){

System.out.println(s);

}

}

}

3.2. Vector使用 (Vector 类可以实现可增长的对象数组)

import java.util.Enumeration;

import java.util.Iterator;

import java.util.Vector;

/**

 * Vector用法和ArrayList基本相同 有序

 * @author Administrator

 *

 */

public class TestVector01 {

public static void main(String[] args) {

//新建集合对象

Vector<String> vec = new Vector<String>();

vec.add("jack");

vec.add("tom");

vec.add("bob");

vec.add("kate");

System.out.println("--------for遍历--------------");

for(int i=0;i<vec.size();i++){

System.out.println(vec.get(i));

}

System.out.println("--------foreach遍历--------------");

for(String s:vec){

System.out.println(s);

}

System.out.println("--------Iterator迭代器遍历--------------");

//获取迭代器对象

Iterator<String> it = vec.iterator();

while(it.hasNext()){

System.out.println(it.next());

}

System.out.println("--------Enumeration迭代器遍历--------------");

//Enumaration Iterator类似的,比较古老的迭代器 ,hasMoreElement()判断是否有值

//nextElement()获取值

//获取迭代器对象

Enumeration<String> en = vec.elements();

while(en.hasMoreElements()){

System.out.println(en.nextElement());

}

}

}

 

原创粉丝点击