Java学习笔记——容器和泛型

Java学习笔记——容器和泛型

容器

Java提供的一套容器类,其中基本类型是List、Set(集)、Queue和Map(映射),这些对象类型也称之为集合类。
Java学习笔记——容器和泛型

列表( List ):数组方式实现,维护元素的索引顺序

– 对象按索引存储
– 可以存储重复元素

  • 主要实现类
    ArrayList:动态数组
    •遍历比较快,插入删除偏慢
    LinkedList:链表
    •双向链表,遍历速度慢,快速插入删除
ArrayList

ArrayList就是动态数组,动态的增加和减少元素,可灵活的设置数组的大小

  • 构造方法
    List list=new ArrayList();
    – import java.util.List; import java.util.ArrayList;
  • 其他方法
    –add(E e):将指定的元素添加到此列表的尾部 // E:任意的对象类型
    –add(int index, E element):将指定的元素插入此列表中的指定位置
    –remove(int index):移除此列表中指定位置上的元素
    –remove(E e):移除此列表中指定元素
    –get(int index):返回此列表中指定位置上的元素
    –set(int index, E element):用指定的元素替代此列表中指定位置上的元素
    –size():返回此列表中的元素数
    –isEmpty():判断是否为空
    –contains(E e):判断是否包含元素
    Java学习笔记——容器和泛型

对于动态数组,有人可能会使用Vector
为什么用ArrayList取代Vector类?
Vector类的方法是同步的,同步操作将耗费大量时间
ArrayList类的方法不是同步的,故建议在不需要同步时使用

集合和数组之间的转换问题

//1.把集合(List,Set)转换为数组
Object[] objs=set.toArray();
//2.把数组转换成集合(List),需要依靠Arrays工具实现
List<Object> list=Arrays.asList(objs);
LinkedList
  • 构造方法
    List names=new LinkedList();
    –//import java.util.List; import java.util.LinkedList;
    Java学习笔记——容器和泛型
    打印结果:
    Java学习笔记——容器和泛型

集(Set)是最简单的一种集合:关心唯一性

–对象无序存储
–不能存储重复元素,不维护元素的索引顺序
主要实现类

  • HashSet:使用被插入对象的Hash码(效率最高),无序,不是同步的,底层通过散列函数来进行元素的存储。
  • LinkedHashSet:继承于HashSet、又基于LinkedHashMap来实现,遍历性能比HashSet好,以元素插入的顺序来维护集合的链接表,在散列函数的基础上添加了链表支持。
  • TreeSet:二叉树结构(通过红黑树生成二叉排序树),保证元素按照元素的自然顺序进行升序排序,添加操作速率比散列集慢,访问和遍历的时间很快

元素添加顺序:B、A、D、E、C、F
Java学习笔记——容器和泛型

HashSet
  • 构造方法
    –HashSet(Collection<? extends E> c)):构造一个散列集,并将集合中的所有元素添加到这个散列集中
    Set name=new HashSet();
    –import java.util.Set; import java.util.HashSet;
  • 其他方法
    –add(E e):如果此 set 中尚未包含指定元素,则添加指定元素
    –clear():从此 set 中移除所有元素
    –remove(Object o):如果指定元素存在于此 set 中,则将其移除
    –size():返回此 set 中的元素的数量(set 的容量)
    –isEmpty():如果此 set 不包含任何元素,则返回 true
    –contains(E e):判断是否包含元素
    Java学习笔记——容器和泛型
    打印结果:
    Java学习笔记——容器和泛型
TreeSet

•构造方法
TreeSet name=new TreeSet();
–import java.util.TreeSet;
–import java.util.Set;
•其他方法
–add():将指定的元素添加到此 set(如果该元素尚未存在 set 中)
–remove(Object o):将指定的元素从 set 中移除(如果该元素存在于此 set 中)
–first():返回此 set 中当前第一个(最低)元素
–last():返回此 set 中当前最后一个(最高)元素
–isEmpty():如果此 set 不包含任何元素,则返回 true
–size():返回 set 中的元素数(set 的容量)
Java学习笔记——容器和泛型
打印结果:
Java学习笔记——容器和泛型

LinkedHashSet
  • 构造方法
    –LinkedHashSet():构造一个带默认初始容量 (16) 和加载因子 (0.75) 的新空链接哈希 set
  • 其他方法
    –包含继承自HashSet的方法:add, clear, isEmpty, remove, size

Queue接口

– java.util.Queue
队列是一种特殊的线性表,只允许在表的前端(front,队头)进行删除操作,而在表的后端(rear,队尾)进行插入操作
LinkedList实现了Queue接 口

  • add(E e): 增加一个元素。成功时返回true,如果队列已满,则抛出一个IIIegaISlabEepeplian异常
  • remove(): 移除并返回队列头部的元素。如果队列为空,则抛出一个NoSuchElementException异常
  • Element(): 返回队列头部的元素。如果队列为空,则抛出一个NoSuchElementException异常
  • offer(E e): 添加一个元素并返回true。如果队列已满,返回false
  • poll(): 移除并返问队列头部的元素。如果队列为空,则返回null
  • peek(): 返回队列头部的元素。如果队列为空,则返回null
  • put(E e): 添加一个元素。如果队列满,则阻塞
  • take(): 移除并返回队列头部的元素。如果队列空,则阻塞

Map接口

Java学习笔记——容器和泛型
对象以键-值对(key-value)存储
key不允许有重复,value允许有重复
Map中元素,可以将key序列、value序列单独抽取出来
–使用keySet()抽取key序列,将map中的所有keys生成一个Set。
–使用values()抽取value序列,将map中的所有values生成一个Collection。(通常转成list)

HashMap
  • HashMap是非线程安全的,无序
  • 常用方法:
    –put(K key,V value)
    –get(Object K) //里面是key
    –size()
    –isEmpty()
    –containsKey(K key)
    –containsValue(V value)
    –keyset()
    –values()
    Java学习笔记——容器和泛型
    打印结果:
    Java学习笔记——容器和泛型
TreeMap

– 基于红黑树实现
– 按照元素的自然顺序排序
Java学习笔记——容器和泛型
打印结果:
Java学习笔记——容器和泛型

LinkedHashMap
  • 维护key值的插入顺序
    Java学习笔记——容器和泛型
    打印结果:
    Java学习笔记——容器和泛型

迭代器(Iterator)

iterator()方法是java.lang.Iterable接口,被Collection继承。

  • 主要功能:用于对容器的遍历
  • Iterator:相当于指针,能够指向集合中的元素(在内存中通过索引表来记录元素的顺序,并在遍历过程中,对该索引表加锁,达到的效果是不允许在遍历过程中改变元素的顺序性),一般不对集合进行编辑操作(不进行添加操作,允许删除)
    Iterator()得到Iterator对象,通过hasNext()方法判断是否遍历结束,通过next()方法移动到指针指向,即指向集合中的下一个元素
  • 主要方法
    –boolean hasNext():判断是否有可以元素继续迭代
    –Object next():返回迭代的下一个元素
    –void remove():从迭代器指向的集合中移除迭代器返回的最后一个元素
//遍历集合
		//通过foreach结构遍历
		for(Student stu:set) {
			System.out.println(stu.getName());
			System.out.println(stu.getAge());
		}
		//通过foreach结构遍历map
		Map<Integer,Student> map=new HashMap();
		map.put(1,lily);
		map.put(2,Lucy);
		System.out.println(map);
		for(Entry<Integer, Student> entry:map.entrySet()) {
			System.out.println(entry.getKey());
			System.out.println(entry.getValue());
		}
		
		//通过索引遍历List
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
		//使用Iterator遍历集合set
		Iterator<Student> it=set.iterator();
		while(it.hasNext()) {
			Student stu=it.next();
			if(stu.getName().equals("lily")) {
				it.remove();
				//set.add(new Student());运行时错误,不允许修改内存中索引顺序表
			}
		}
		System.out.println(set);
		
		//使用Iterator遍历map
		Iterator<Integer> itinteger=map.keySet().iterator();//遍历所有key组成的set集合
		Iterator<Student> itStudent=map.values().iterator();//遍历所有value组成的集合
		Iterator<Entry<Integer,Student>> itEntry =map.entrySet().iterator();//遍历map集合中所有元素组成的set集合,集中每一个元素的类型是entry类型
		while(itEntry.hasNext()) {
			Entry entry=(Entry)it.next();
			entry.getKey();//得到元素的key
			entry.getValue();//得到元素的value
			}

泛型(Generics)

所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。
泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。
泛型赋予了代码更强的类型安全,更好的复用,更高的效率,更清晰的约束。

  • Java 中的泛型只接受引用类型作为类型参数。
    –如:可以定义 List,不可以定义 List。
  • 语法
    class 名称<泛型列表>
    如:class ArrayList< E >
    –参数E是泛型,它可以是任何类或接口(除基本数据类型外)
  • 集合中使用泛型
    List< E >
    方法参数:
    void do(List< Dog > dogs){…}
    返回类型:
    –List< Dog> getDogs(){…}
    变量声明的类型必须匹配传递给实际对象的类型
使用通配符:
  • 接受所声明变量类型的任何子类型
    –void addAnimal(List<? extends Animal> animals)
    –Animal可以是类或接口
  • 接受父类型的变量
    –void addAnimal(List<? super Dog> animals)
    –接受super右边类型或其超类型
  • List<?> 与List<? extends Object>完全相同
  • List与List<?>完全不同
  • 泛型通配符只能用于引用的声明中,不可以在创建对象时使用(不能出现在等号右面)
    –Fruit<?> fruit=new Fruit<?>();×