java第二册—02集合与泛型

                                                 集合与泛型

一、集合框架

集合又称为容器,用于存储、提取、删除数据。JDK提供的集合API都包含在 java.util 包内。

集合框架两大分支:Collection接口和Map接口。

两张图搞懂各种集合之间的关系

二、List接口

概述:

List接口继承Collection接口。该接口属于数据结构中的线性结构,用户可以根据元素的整数索引来访问元素;

List接口实现类:

ArrayList(数组线性表)
    1、List 接口的实现类。其内部基于一个大小可变数组来存储
    2、允许存储 null 元素
LinkedList(双向链表)
    1、List 接口的链接列表实现类
    2、允许存储 null 元素
Vector(向量)
    1、功能和ArrayList一样
    2、线程安全
Stack(栈)
    1、 表示后进先出(LIFO)的对象堆栈

常用方法

add(Object element) 向列表的尾部添加指定的元素
size()  返回列表中的元素个数
get(int  index)   返回列表中指定位置的元素,index从0开始

import java.util.ArrayList;
import java.util.List;

public class ListTest {
	public static void main(String[] args) {
		List<String> nameList = new ArrayList<String>();
		nameList.add("张三");
		nameList.add("王五");
		int size = nameList.size();//获取列表中元素个数
		System.out.println(size);//输出2
		String name = nameList.get(1);
		System.out.println(name);//输出王五
	}
}

add(int index, Object element)  在列表的指定位置插入指定元素
set(int i, Object element) 将索引i位置元素替换为元素element并返回被替换的元素。
clear()  从列表中移除所有元素
isEmpty()  判断列表是否包含元素,不包含元素则返回 true,否则返回false

import java.util.ArrayList;
import java.util.List;

public class ListTest {
	public static void main(String[] args) {
		List<String> nameList = new ArrayList<String>();
		nameList.add("张三");
		nameList.add("王五");
		String name = nameList.set(0,"李四");
        System.out.println("原来的数据为"+name);//输出结果:“原来的数据为张三”
        System.out.println("替换后的数据为"+nameList.get(0));//输出结果为“替换后的数据为李四”
        nameList.clear();
        System.out.println(nameList.isEmpty);//输出结果为true
        
	}
}

iterator()  返回按适当顺序在列表的元素上进行迭代的迭代器

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator

public class ListTest {
	public static void main(String[] args) {
		List<String> nameList = new ArrayList<String>();
		nameList.add("张三");
		nameList.add("王五");
		nameList.add("李四");
        Iterator <String> iterator = nameList.iterator;
        while(iterator.hasNext()){
            System.out.println(iterator.next);//List集合的遍历
        }
	}
}

contains(Object o)  如果列表包含指定的元素,则返回 true。

import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
		List<String> nameList = new ArrayList<String>();
		nameList.add("张三");
		if(nameList.contains("张三")){
			System.out.println("包含");
		}else{
			System.out.println("不包含");
		}
	}
}

说明o指传入方法的具体值,e指集合中的某一个元素,该三目表达式有以下四种情形:
1、如果o的值为null,则只有集合中存在null元素才会返回true;
2、如果o为String类型的对象,则只有集合中存在满足o.equals(e)条件的元素e时才会返回true ,其实质是运行时类型相同的前提下比较两者字符串是否完全相同
3、如果o为基本数据类型包装类对象,则只有集合中存在满足o.equals(e)条件的元素e时才会返回true,其实质是在两者运行时类型相同的前提下比较两者的值是否相等
4、如果o为自定义类类型对象,则只有集合中存在满足o.equals(e)条件的元素e时才会返回true,其实质是在两者运行时类型相同且自定义类没有重写equals方法的前提下比较两者的地址是否相等

remove(int  index)  移除列表中指定位置的元素,并返回被删元素
remove(Object o)  移除集合中第一次出现的指定元素,移除成功返回true,否则返回false。

LinkedList除了实现List提供的抽象方法外,还增加了一些方法:

void  addFirst(Object o) 将指定数据元素插入此集合的开头,原来元素(如果有)后移;
void addLast(Object o) 将指定数据元素插入此集合的结尾
Object getFirst() 返回此集合的第一个数据元素
Object getLast() 返回此集合的最后一个数据元素
Object removeFirst() 移除并返回集合表的第一个数据元素
Object removeLast() 移除并返回集合表的最后一个数据元素

ArrayList线性表与数组的区别:

1. 两者本质的区别在与长度是否可变
数组是定长有序的线性集合
线性表是任意长度的线性集合
2. 两者添加元素的方式不同
数组:使用下标:array [index]
数组线性表:使用add方法:list.add(value) 
3. 两者获取元素的方式不同
数组:使用下标:array [index]
数组线性表:使用get方法:list.get(index) 
4. 获取长度的方式不同
数组:length属性
数组线性表:size()方法 

ArrayList、LinkList和Vector的区别

ArrayList是基于动态数组存储的数组线性表数据结构,使用连续的内存单元存储数据元素,对元素的遍历速度较快,LinkedList在遍历集合元素方面比较慢,因为在遍历过程中需要找寻下个元素的地址;

LinkedList是使用指针关联的双向链表数据结构,前一个元素都记录了后一个元素的地址,后一个元素也记录了前一个元素的地址,当添加或删除数据元素时,LinkedList比较快,因为ArrayList需要移动其被添加(或删除)元素后面(最后一个除外)的全部元素;

Vector是线程安全(synchronized)的,而ArrayList是非线程安全的,所以调用方法名相同的方法时,Vector对象要比ArrayList对象稍慢一些。

三、Set集合

概述

–Set接口继承Collection接口

Set接口常用实现类

HashSet
    1、实现了 Set 接口
    2、“它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变”
    3、允许使用 null 元素
LinkedHashSet
    1、HashSet的子类
    2、由于该实现类对象维护着一个运行于所有元素的双重链接列表,由于该链接列表定义了迭代顺序,所以在遍历该实现类集合时按照元素的插入顺序进行遍历
TreeSet
    1、既实现Set接口,同时也实现了SortedSet接口,具有排序功能
    2、存入TreeSet中的对象元素需要实现Comparable接口

结合JDK API文档讲解这些类之间的区别,可通过提问或总结的形式让学员来回答

HashSet的遍历顺序:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetTest {
	public static void main(String[] args) {
		Set<String> nameList = new HashSet<String>();
		nameList.add("小马");
		nameList.add("小杨");
		nameList.add("小李");
		Iterator<String> iterator = nameList.iterator();
		while(iterator.hasNext()){
			System.out.println(iterator.next());
		}
	}
}

LinkedHashSet的遍历顺序:
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

public class SetTest {
	
	public static void main(String[] args) {
		Set<String> nameList = new LinkedHashSet<String>();
		nameList.add("小马");
		nameList.add("小杨");
		nameList.add("小李");
		Iterator<String> iterator = nameList.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
}

常用方法

add(Object obj):向Set集合中添加元素,添加成功返回true,否则返回false
size() :返回Set集合中的元素个数
remove(Object  obj) : 删除Set集合中的元素,删除成功返回true,否则返回false。
isEmpty() :如果Set不包含元素,则返回 true ,否则返回false
clear() : 移除此Set中的所有元素
iterator() :返回在此Set中的元素上进行迭代的迭代器
contains(Object o):如果Set包含指定的元素,则返回 true,否则返回false
 

Person类:
public class Person {
	
	int age;//年龄
	String name;//姓名
}

测试类:
import java.util.HashSet;
import java.util.Set;

public class SetTest {
	
	public static void main(String[] args) {
//obj=null时
		Set<Double> set = new HashSet<Double>();
		set.add(null);
		set.add(null);
		System.err.println(set.size());//输出1——添加null元素时,如果Set集合中已经存在null元素,则不再添加待add的null数据

//obj=基本数据类型封装类对象
    	Set<Double> set = new HashSet<Double>();
		Double d1 = new Double(1);
		Double d2 = new Double(1);
		Double d3 = new Double(2);
		set.add(d1);
		set.add(d2);//由于添加d2以前Set集合中已经有了一个值为1的Double类型对象,而d2.equals(d1)为true(基本数据类型的equals方法比较的是值是否相等),所以d2无法添加到Set集合中
		set.add(d3);
		System.err.println(set.size());//输出2
		
obj=String类对象	
    	Set<String> set = new HashSet<String>();
		String str1="111";
		String str2=new String("111");
		String str3=new String("333");
		set.add(str1);
		set.add(str2);//由于添加str2以前Set集合中已经有了一个内容和str2相同的字符串,即str2.equals(str1)为true(String类的equals方法比较的是字符串内容是否相同),所以str2无法添加到Set集合中
		set.add(str3);
		System.err.println(set.size());//输出2

		
        //obj=其它引用类型对象
		Set<Person> set = new HashSet<Person>();
		Person p1 = new Person();
		Person p2 = p1;
		Person p3 = new Person();
		set.add(p1);
		set.add(p2);//由于添加p2以前Set集合中已经有了一个地址和p2相同的对象,即p2.equals(p1)为true(其它类型的equals方法比较的是地址是否相同),所以p2无法添加到Set集合中
		set.add(p3);
		System.err.println(set.size());//2
	}
}
Person类:
public class Person {
	
	int age;//年龄
	String name;//姓名
}

测试类:
import java.util.HashSet;
import java.util.Set;

public class SetTest {

	public static void main(String[] args) {
//obj=null时
		Set<Double> set = new HashSet<Double>();
		set.add(null);
		System.out.println(set.size());//1
		set.remove(null);//删除成功,因为集合中也有一个null
		System.out.println(set.size());//0
		
//obj=基本数据类型封装类对象
		Set<Double> set = new HashSet<Double>();
		Double d1 = new Double(1);
		set.add(d1);
		System.out.println(set.size());//1
		Double d2 = new Double(2);
		set.remove(d2);//删除失败,因为d2所指代的数值与集合中已有的数值不相等
		System.err.println(set.size());//1
		Double d3 = new Double(1);
		set.remove(d3);//删除成功,因为d2所指代的数值与集合中已有的数值相等
		System.err.println(set.size());//0
		
//obj=Sting类对象	
		Set<String> set = new HashSet<String>();
		set.add("111");
		System.err.println(set.size());//1
		String str1=new String("222");
		set.remove(str1);//删除失败,因为str1所指代的字符串与集合中已有的字符串内容不同
		System.err.println(set.size());//1
		String str2=new String("111");
		set.remove(str2);//删除成功,因为str1所指代的字符串与集合中已有的字符串内容相同
    	System.err.println(set.size());//0
		
//obj=其它引用类型对象
		Set<Person> set = new HashSet<Person>();
		Person p1 = new Person();
		set.add(p1);
		System.err.println(set.isEmpty());//false
		set.remove(new Person());//删除失败,因为此处Person对象和set集合中已有的对象地址不相同
		System.err.println(set.isEmpty());//false
		set.remove(p1);//删除成功,因为此处Person对象和set集合中已有的对象地址相同,属于同一个对象
		System.err.println(set.isEmpty());//false
	}
}

使用HashSet存储自定义类对象时,可以在自定义类中重写equals和hashCode方法避免“真实”对象被多次存入,主要原因是集合内不允许有重复的数据元素,在集合校验元素的有效性时(数据元素不可重复),需要调用equals和hashCode验证。

HashSet集合对象如何判断数据元素是否重复:

            检查待存对象hashCode值是否与集合中已有元素对象hashCode值相同,如 果hashCode不同则表示不重复, 如果hashCode相同再调用equals方法进一步检查,equals返回真表示重复,否则表示不重复。 

TreeSet是一个有序集合,其元素按照升序排列,默认是按照自然顺序排列,也就是说TreeSet中的对象元素需要实现Comparable接口。

TreeSet虽然是有序的,但是并没有具体的索引,当插入一个新的数据元素的时候,TreeSet中原有的数据元素可能需要重新排序,所

TreeSet插入和删除数据元素的效率较低。

四、map接口

概述

Map集合基于 键(key)/值(value)映射。每个键最多只能映射一个值。键可以是任何引用数据类型的值,不可重复;值可以是任何引用数据类型的值,可以重复;键值对存放无序。

Map常用实现类

HashMap
    允许使用 null 值和 null 键;此类不保证映射的顺序;在多线程操作下不安全
LinkedHashMap
    基于哈希表和链接列表的实现类;具有可预知的迭代顺序(双重链接表的有序性)
Properties
    Hashtable的一个子类;属性列表中每个键及其对应值都是一个字符串;在多线程操作下安全

常用方法

put(K key, V value) 将键(key)/值(value)映射存放到Map集合中
get(Object key) 返回指定键所映射的值,没有该key对应的值则返回 null
size()  返回Map集合中数据数量

import java.util.HashMap;
import java.util.Map;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		System.out.println(studentMap.size());//返回 0
		studentMap.put("002", "小王");//向集合中保存数据
		System.out.println(studentMap.get("002"));//返回“小王”
		System.out.println(studentMap.size());//返回 1
	}
}

clear() 清空Map集合
isEmpty () 判断Map集合中是否有数据,如果没有则返回true,否则返回false

import java.util.HashMap;
import java.util.Map;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		studentMap.put("002", "小王");
		studentMap.put("001", "小李");
		
		System.out.println(studentMap.isEmpty());//返回false
		studentMap.clear();//删除集合中所有数据
		System.out.println(studentMap.isEmpty());//返回true
	}
}

remove(Object key) 删除Map集合中键为key的数据并返回其所对应value值。

import java.util.HashMap;
import java.util.Map;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		studentMap.put("001", "小李");
		
		System.out.println(studentMap.isEmpty());//返回false
		System.out.println(studentMap.remove("001"));//返回“小李”
		System.out.println(studentMap.isEmpty());//返回true
	}
}

values()  返回Map集合中所有value组成的以Collection数据类型格式数据。

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		studentMap.put("002", "小王");
		studentMap.put("001", "小李");
		
		Collection<String> valueCollection = studentMap.values();
		for (String data :valueCollection) {
			System.out.println(data);
		}
		
		Iterator<String> valueIterator = valueCollection.iterator();
		while(valueIterator.hasNext()){
			String data = valueIterator.next();
			System.out.println(data);
		}
	}
}

containsKey(Object key)  判断集合中是否包含指定键,包含返回 true,否则返回false

containsValue(Object value)  判断集合中是否包含指定值,包含返回 true,否则返回false

import java.util.HashMap;
import java.util.Map;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		studentMap.put("001", "小李");
		
		System.out.println(studentMap.containsKey("001"));//返回true
		System.out.println(studentMap.containsValue("小李"));//返回true
	}
}

keySet()  返回Map集合中所有key组成的Set集合

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		studentMap.put("002", "小王");
		studentMap.put("001", "小李");
		
		Set<String> keySet = studentMap.keySet();
		for (String key : keySet) {
			String value = studentMap.get(key);
			System.out.println(key+":"+value);
		}
		
		Iterator<String> keyIterator = keySet.iterator();
		while(keyIterator.hasNext()){
			String key = keyIterator.next();
			String value = studentMap.get(key);
			System.out.println(key+":"+value);
		}
	}
}

entrySet()  将Map集合每个key-value转换为一个Entry对象并返回由所有的Entry对象组成的Set集合

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Test {
	
	public static void main(String[] args) {
		Map<String, String> studentMap = new HashMap<String, String>();
		studentMap.put("002", "小王");
		studentMap.put("001", "小李");
		
		Set<Entry<String, String>> studentSet = studentMap.entrySet();
		for (Entry<String, String> entry : studentSet) {
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key+":"+value);
		}
		
		Iterator<Entry<String, String>> studentIterator=studentSet.iterator();
		while(studentIterator.hasNext()){
			Entry<String, String> entry = studentIterator.next();
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key+":"+value);
		}
	}
}

五、工具类

工具类最主要特征是提供了一系列对集合的操作,例如排序、随机输出等等。Java集合

框架提供了两个常见的工具类:Collections和Arrays,另外,结合前面TreeSet讲解的比较器接

口Comparable,我们针对List集合的数据如何排序?还需要讲解Comparator接口,为了区分,

我们通常将Comparable称之为内部比较器,而将Comparator称之为外部接口。

常用方法

max(Collection <? extends T> coll)根据元素的自然顺序,返回给定集合元素中的最大元素

min(Collection <? extends T> coll)根据元素的自然顺序,返回给定集合元素中的最小元素

示例1:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

	public static void main(String[] args) {
		List<Integer> digitList = new ArrayList<Integer>();
		digitList.add(1);
		digitList.add(3);
		digitList.add(2);
		int maxDigit = Collections.max(digitList);
		System.out.println(maxDigit);//输出3
		
		List<String> stringList = new ArrayList<String>();
		stringList.add("af");
		stringList.add("c");
		stringList.add("ad");
		String minString = Collections.min(stringList);
		System.out.println(minString);//输出ad
	}
}

示例2:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		list.add(new Student());
		list.add(new Student());
		Collections.max(list);
	}
}

class Student{

}

sort(List<T> list) :根据元素的自然顺序对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口。

示例1:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		List<Integer> digitList = new ArrayList<Integer>();
		digitList.add(1);
		digitList.add(3);
		digitList.add(2);
		Collections.sort(digitList);
		for(Integer data : digitList){
			System.out.println(data);
		}
		
		List<String> stringList = new ArrayList<String>();
		stringList.add("af");
		stringList.add("c");
		stringList.add("ad");
		Collections.sort(stringList);
		for(String data : stringList){
			System.out.println(data);
		}
	}
}

示例2:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		list.add(new Student());
		list.add(new Student());
		Collections.sort(list);
		for(Student student : list){
			System.out.println(student);
		}
	}
}

class Student{

}

sort(List<T> list, Comparator<? super T> c)   根据指定比较器产生的顺序对指定列表进行排序

代码1:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		List<Integer> digitList = new ArrayList<Integer>();
		digitList.add(1);
		digitList.add(3);
		digitList.add(2);
		Collections.sort(digitList, new Comparator<Integer>() {

			@Override
			public int compare(Integer a, Integer b) {
				return a-b;
			}
		});
		for(Integer data : digitList){
			System.out.println(data);
		}
	}
}

代码2:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		list.add(new Student());
		list.add(new Student());
		Collections.sort(list, new Comparator<Student>() {
			@Override
			public int compare(Student stu1, Student stu2) {
				return stu1.hashCode() - stu2.hashCode();
			}
		});
		for(Student student : list){
			System.out.println(student);
		}
	}
}

class Student{

}

reverse(List<?> list):反转指定列表中元素的顺序

代码1:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		List<Integer> digitList = new ArrayList<Integer>();
		digitList.add(1);
		digitList.add(3);
		digitList.add(2);
		for(int data : digitList){
			System.out.println(data);
		}
		System.out.println("~~~~~~~~~");
		Collections.reverse(digitList);
		for(int data : digitList){
			System.out.println(data);
		}
	}
}

代码2:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		list.add(new Student());
		list.add(new Student());
		Collections.reverse(list);
		for(Student student : list){
			System.out.println(student);
		}
	}
}

class Student{

}

swap(List<?> list, int i, int j):在指定列表的指定位置处交换元素,如果指定位置相同,则调用此方法不会更改列表。

代码1:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		List<Integer> digitList = new ArrayList<Integer>();
		digitList.add(1);
		digitList.add(3);
		digitList.add(2);
		for(Integer data : digitList){
			System.out.println(data);
		}
		System.out.println("~~~~~~~~~");
		Collections.swap(digitList, 0, 2);
		for(int data : digitList){
			System.out.println(data);
		}
	}
}

代码2:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		list.add(new Student());
		list.add(new Student());
		Collections.swap(list,0,1);
		for(Student student : list){
			System.out.println(student);
		}
	}
}

class Student{

}

binarySearch(List<? extends Comparable<? super T>> list, T key) :返list集合元素按照自然顺序升序排序后,使用二分搜索法搜索list集合,返回指定对象的索引,如果没找到返回-1

代码1:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		List<Integer> digitList = new ArrayList<Integer>();
		digitList.add(1);
		digitList.add(3);
		digitList.add(2);
		Collections.sort(digitList);
		int digitIndex = Collections.binarySearch(digitList, 2);
		System.out.println(digitIndex);//输出1
		
		List<String> stringList = new ArrayList<String>();
		stringList.add("af");
		stringList.add("c");
		stringList.add("ad");
		Collections.sort(stringList);
		int stringIndex = Collections.binarySearch(stringList, "c");
		System.out.println(stringIndex);//输出2
	}
}

代码2:
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Integer> list=new LinkedList<Integer>();
		list.add(1);
		list.add(2);
		list.add(-1);
		//Collections.sort(list);
		int index=Collections.binarySearch(list, -1);
		System.out.println(index);//使用binarySearch(List<? extends Comparable<? super T>> list, T key) 方法前如果不先按自然顺序升序排列,则其结果不准确
	}
}

代码3:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {

	public static void main(String[] args) {		
		List<Student> list = new ArrayList<Student>();
		Student student=new Student();
		list.add(new Student());
		list.add(new Student());
		int index = Collections.binarySearch(list, student);
		System.out.println(index);
	}
}

class Student{

}
/**注意:
  *1、使用该方法前必须保证集合中的数据是升序排列的,否则结果不正确(详见备注示例2)
  *2、在使用该方法时存入集合中的对象对应的类必须实现Comparable接口,否则程序在编译阶段就会报错。 
  *(详见备注示例3)
  */

Comparable接口

String和各种包装类已经实现了Comparable接口
TreeSet集合内默认是按照自然顺序排序的
在集合内元素之间的比较,由该类的compareTo(Object o)方法来完成,因为这种比较是在类内部实现,所以将Comparable称为内部比较器

Comparator

外部比较器
配合Collections工具类的sort(List list, Comparator c)方法使用。
当集合中的对象不支持自比较或者自比较的功能不能满足需求时使用
和内部比较器相比,其可重用性好

六、自动拆箱和自动装箱

自动拆箱和装箱是从JDK5.0才开始有的,它方便了基本数据类型和其对应的包装类型之间的转换。

将一个基本数据类型的值赋给其所对应的包装类型称之为自动装箱;将一个基本数据类型包装类类型的值赋给其所对应的基本数据类型称之为自动拆箱。

public class Test {

	public static void main(String[] args) {
		Integer i =100; //自动装箱
		System.out.println(i);//输出100
		int j = i; //自动拆箱
		System.out.println(j);//输出100
	}
}

自动拆箱和装箱的过程由编译器自动完成:通过包装类的valueOf方法将基本数据类型包装成引用类型;通过包装类对象xxxValue方法将引用类型变为对应的基本类型,所以上页代码经过编译器编译后为:

public class Test {

	public static void main(String[] args) {
		Integer i =Integer.valueOf(100);
		System.out.println(i);//输出100
		int j = i.intValue();
		System.out.println(j);//输出100
	}
}

Java对部分经常使用的数据采用缓存技术,即第一次使用该数据则创建该数据对象并对其进行缓存,当再次使用等值对象时直接从缓存中获取,从而提高了程序执行性能。

public class Test {

	public static void main(String[] args) {
		Integer i =12;
		Integer j =12;
		System.out.println(i==j);//输出true
	}
}

Java中只是对部分基本数据类型对应包装类的部分数据进行了缓存:

byte、short、int和long所对应包装类的数据缓存范围为 -128~127(包括-128和127);

七、泛型

概述

JDK5以后, Java引入了“参数化类型(parameterized type)”的概念, 该概念也称之为泛型(Generic)。所谓泛型就是允许在定义类、接口或方法时使用类型形参,该类型形参将在声明变量、创建对象或者调用方法时动态指定(即传入实际的类型参数,可称为类型实参)

优点

–泛型的出现简化了代码,提高了程序的健壮性。

泛型接口,Java5改写了集合框架中的全部接口,下面以List和Map接口中的部分代码为例展示泛型接口的定义:
 

示例1:
import java.util.Collection;

//定义接口时指定一个类型形参E,在此处定义好后可在整个接口体中当做类型使用
public interface List<E> extends Collection<E> {

    boolean add(E e);

    E get(int index);

    E set(int index, E element);
}

泛型类,泛型不仅仅可以在定义接口是可以使用,定义类时同样可以使用,下面以Map接口实现类HashMap中的部分代码为例展示泛型类的定义:

import java.util.Set;

interface Map<K,V> {

    V get(Object key);

    V put(K key, V value);

    Set<K> keySet();
}
//定义实现了Map接口的实现类HashMap,在定义本类中使用了泛型形参。定义类时使用的泛型形参可以在整个类体中被使用
public class HashMap<K,V> implements Map<K,V>{

    public V get(Object key) {
        return null;
    }

    public V put(K key, V value) {
        V v=null;
        return v;
    }

    public Set<K> keySet() {
        Set<K> ks = null;
        return ks;
    }
}

泛型方法(Generic Method)指声明一个带有定义一个或多个类型形参的方法.

如何定义泛型方法:

访问控制符 [修饰符] <类型形参1,类型形参2…… > 返回值类型 方法名( [参数] )  {

           //方法体……

}

如果定义的泛型方法有修饰符,则泛型方法中的类型形参列表必须放在方法返回值类型之前,修饰符之后;如果定义的泛型方法没有修饰符,则泛型方法中的类型形参列表必须放在方法返回值类型之前,访问控制符之后;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Test{

	public static <T> void sortList(List<T> list, Comparator<T> comparator){
		Collections.sort(list, comparator);
	}
}

如何使用泛型方法:

与类和接口中使用泛型参数不同,使用泛型方法时无须为方法中定义的泛型参数显示传入实际类型参数,编译器会根据实际数据推断该泛型参数的实际类型

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Test{

	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(3);
		list.add(2);
		list.add(1);
		for (int data : list) {
			System.out.println(data);
		}
		System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
		Comparator<Integer> comparator = new Comparator<Integer>(){

			@Override
			public int compare(Integer a, Integer b) {
				return a-b;
			}
		};
		sortList(list, comparator);
		for (int data : list) {
			System.out.println(data);
		}
	}
	
	public static <T> void sortList(List<T> list, Comparator<T> comparator){
		Collections.sort(list, comparator);
	}
}

使用带有泛型类型的类、接口和方法时,如果无法判断其泛型类型,可以只用类型通配符?来代替。

import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
		List list = new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		list.add("王五");
		loop(list);
	}
	
	public static void loop(List<?> list){
		for(Object data : list){
			System.out.println(data);
		}
	}
}

注意
类型通配符不能用于声明含有泛型的接口、类或方法
如果将类型通配符用于诸如集合泛型,则除null外不能像其中添加元素,只能遍历元素。

import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
		List<?> list = new ArrayList<String>();
		list.add(null);
		list.add("张三");
		for(Object data : list){
			System.out.println(data);
		}
	}
}

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值