集合和泛型

xiaoxiao2021-02-28  108

JAVA主要的集合体系

JAVA集合的接口和具体实现是分离的;

JAVA的集合框架中有两个基本的集合接口,一个是Collection,还有一个是Map, Collection继承 Iterable接口,这个接口允许对象成为 “foreach” 语句的目标; Collection接口有比较实用的实现方式:有序列表list 无序列表Set 和队列Queue。

在 Java集合类框架里有两个类叫做Collections提供了封装器实现、数据结构算法和数组相关的应用。

三大集合接口简述

常用的集合接口有List、Set、Map三个以及其实现类,集合的常用接口和实现方式在java.util工具包下面。

List:有序列表,存储空间是有下标的,可以按位置存取。

Set:散列集合,存储空间没有下标。

前两者都是Collection的子接口

Map:键值对,根据键值K取V,键值K是唯一的。

List:

集合中最常见的一个集合是有序列表list:

List接口是有序的列表,与父类 Collection比包含了Collection所有的方法,又扩展了能精确地控制每个位置上的元素的方法。 如: list.get(i)读取第i位置的元素; add(int index, E element)指定位置添加元素; remove(int index)移除指定位置的元素; set(int index, E element)替换指定索引位置的元素; subList(int fromIndex, int toIndex)截取子列表。

List有三种实现方式:ArrayList、Vector和LinkedList都是同一个接口的实现,所以操作和方法都是相同的,但是具体的实现方式不一样。

ArrayList:数组实现方式,查询速度快,按位增删速度慢; LinkedList:链表的实现方式,按位增删速度快,查询速度慢; Vector:多线程时线程同步的,保证数据安全。 例:

import java.util.ArrayList; import java.util.List; public class ListDemo { public static void putData2List(String statement, List<String> list) { String pattern = "\\s|,"; String[] words = statement.split(pattern); for (int i = 0; i < words.length; i++) { list.add(words[i]); } } public static void main(String[] args) { String statement = "Yesterday is history,Tomorrow is mystery,But today is a gift"; List<String> list = new ArrayList<String>(); // 将数组的数据放到List中 putData2List(statement, list); //增强for循环 for (String w : list) { System.out.print(w + " "); } } }

Set

无序列表Set 是一个散列的集合,数据会按照散列值存储的,如果两个元素的散列值相同,会存储在同一个地址中,所以看到的就是只有一个元素在集合中了。

Set的特征是: 不会出现重复的元素(按照equals 和hashCode 的规则比较是否重复) Set属于Collection的子接口,拥有Collection的所有的方法; Set 是散列存储没有位置编号,没有按照编号进行操作的方法。

Set有三种

HashSet:散列集合里存储的对象必须正确重写hashCode和equals方法, 可是实现快速查找

TreeSet:树集集合通过二叉树算法保证无重复元素,并对元素进行排序(自然顺序)

LinkedHashSet : 具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。在使用迭代器遍历Set时,结果会按元素插入的次序显示。

例: 用Set查重

import java.util.*; public class SetTest{ public static void main(String[] args) { String statement="A year from now,you will wish you had started today"; int cnt=wordReplace(statement); System.out.println("不重复的单词个数是:"+ cnt); } public static int wordReplace(String statement) { // TODO Auto-generated method stub Set<String> words =new HashSet<String>(); //分割字符串 String pattern = "\\s|,"; String[] word = statement.split(pattern); for ( int i = 0; i < word.length; i++) { words.add(word[i]); } return words.size(); } }

Map

Map映射容器

Map(映射)是一个可以根据键值进行存储的,它的一个 Key 对应的是一个存储的位置,所以Key值是唯一的,根据Key值可以获取到对应的存储的Value。

这种存储的集合我们称为 “键-值” Map。 1)它不是集合Collection的子类; 2) 它的键值是唯一的,根据键值可以取出值; 3) 根据值无法直接取出Key。

Map的几种实现方式:

HashMap 按照散列存储,这样的存取较快,线程不安全的,允许存放null键,null值

Hashtable 线程安全,速度慢,不允许存放null键,null值

TreeMap 使用二叉树的算法来实现键值的自然排序功能。

Map也拥有很多实用的操作方法,如:containsKey(Object key)、equals(Object o)等,如果判断的对象是自定义的对象,需要正确重写equals和hashCode方法才能满足我们想要的结果

Map的键值可以是对象,Map

Map<String,String> map = new HashMap<String,String>(); //Map为接口,key值指定String类型,value指定为String类型。 //存储操作: map.put("key1","value1"); map.put("key2","value1");//value值是可以重复的 //读取操作 map.get("key1"); //key值唯一,重复输入会覆盖

例:

用Map统计文本单词出现次数

import java.util.HashMap; import java.util.Map; public class MapDemo2 { public static void main(String[] args) { String statement="no pain,no gain"; Map<String,Integer> map=MapDemo2.wordCount(statement); System.out.println(map); } public static Map<String, Integer> wordCount(String statement) { Map<String, Integer> s = new HashMap<String, Integer>(); String[] str = statement.split("\\s|,"); for (int i = 0; i < str.length; i++) { if(s.containsKey(str[i])){ s.put(str[i],s.get(str[i])+1); } else{ s.put(str[i],1); } } return s; } }

Collections类

Collections类提供了丰富的静态方法:

binarySearch:折半查找。 add(E e):确保此 collection 包含指定的元素 addAll(Collection

public class person implements Comparable<person>{ public int compareTo(person per) { return (this.getAge()-per.getAge()); } }

如果不愿意实现Comparable接口,可以用另一种方法按照比较器规则排序,有没有实现接口无所谓,因为有比较器。

比如,员工技能按照编号排序又能按照工资排序,一个排序接口如何支持两种呢?有了比较器接口就不一样了,它不需要在本类上实现,可以编写比较规则实现类。

如汽车比较器可以这样写:

按照速度的比较器

public class CarSpeedComparator implements Comparator<Car>{ @Override public int compare(Car car1, Car car2) { return (car1.getSpeed()-car2.getSpeed()); } }

按照重量的比较器

public class CarWeightComparator implements Comparator<Car>{ @Override public int compare(Car car1, Car car2) { return (car1.getWeight()-car2.getWeight()); } }

比较时可以根据场景不同指定不同的比较器

sort(list, speedComparator); //或者 sort(list,weightComparator);

泛型

JAVA的集合是可以存储多个数据类型的:

Collection coll=new ArrayList();

在coll中可以存储除了基本数据类型(装箱为包装类存储)的一切对象。就是说可以存储Integer String Employee,所以在读取的时候是无法知道其准确的类型是什么的。

需要强制类型转换,除非事先知道类型否则会出现类型转换异常,这样程序的安全性就降低。

使用泛型,就是在编译阶段限定其存储的类型是什么,这样就不能随便存储其他类型了,读取时也不需要强制类型转换了。

集合中使用泛型来指定参数类型:可以让代码更安全健壮,也不需使用强制类型转换了。

转载请注明原文地址: https://www.6miu.com/read-53132.html

最新回复(0)