Java入门系列-19-泛型集合
集合
如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足。
如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架。
Java 集合框架提供了一套性能优良、使用方便的接口和类,位于 java.util 包中。
接口 Collection 存储一组不唯一,无序的对象,它有两个子接口 List和Set。List 接口存储一组不唯一,有序(插入顺序)的对象。Set 接口存储一组唯一,无序的对象。
接口 Map 存储一组键值对象,提供 key 到 value 的映射
List 接口的实现类
ArrayList
ArrayList 实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较高。
下面演示使用及常用方法
//Book类存储书的信息 public class Book { private String name;//书名 private float price;//价格 public Book() { super(); } public Book(String name, float price) { super(); this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
测试类
import java.util.ArrayList; import java.util.List; public class TestArrayList { public static void main(String[] args) { List books=new ArrayList();//创建集合 //向集合中添加元素 books.add(new Book("80天环游世界",34.6f)); books.add(new Book("Java核心技术",88)); books.add(new Book("Java编程思想",122)); //获取集合的长度 System.out.println("集合的长度:"+books.size()); //指定索引移除一个元素 books.remove(0); System.out.println("移除后集合的长度:"+books.size()); //for循环遍历 ArrayList for (int i = 0; i < books.size(); i++) { Book book=(Book) books.get(i); System.out.println("书名:"+book.getName()+" 价格:"+book.getPrice()); } //foreach 遍历 ArrayList for (Object object : books) { Book book=(Book) object; System.out.println("书名:"+book.getName()+" 价格:"+book.getPrice()); } //插入元素到指定索引,其余元素自动后移 books.add(0, new Book("明朝那些事儿",55)); //移除指定索引元素 books.remove(2); //清空所有元素 books.clear(); System.out.println("清空集合的长度:"+books.size()); } }
这里面的方法在 Java API 文档中都能查到,一定要学会查看帮助文档。
LinkedList
LinkedList 采用链表存储方法。插入、删除元素时效率比较高。LinkedList提供了对头部和尾部元素进行添加和删除的方法。
下面看一下操作链表集合
import java.util.LinkedList; public class TestLinkedList { public static void main(String[] args) { LinkedList books=new LinkedList();//创建链表集合 //向集合中添加元素 books.add(new Book("80天环游世界",34.6f)); //向集合首部添加元素 books.addFirst(new Book("Java核心技术",88)); //向集合尾部添加元素 books.addLast(new Book("Java编程思想",122)); System.out.println(books.size()); //获取第一个 Book book1=(Book) books.getFirst(); System.out.println("书的名字:"+book1.getName()); //获取最后一个 Book lastBook=(Book) books.getLast(); System.out.println("最后一本书的名字:"+lastBook.getName()); //移除第一个元素 books.removeFirst(); System.out.println("集合长度:"+books.size()); //移除最后一个元素 books.removeLast(); System.out.println("集合长度:"+books.size()); } }
LinkedList也实现于List接口,所以在ArrayList示例中使用的方法LinkedList都有,LinkedList独有的方法在上例中,单独记忆即可。
Map
Map接口专门处理键值映射数据的存储,可以根据键实现对值得操作,最常用的实现类是HashMap,Map的键不允许重复。
import java.util.HashMap; import java.util.Map; public class TestMap { public static void main(String[] args) { Map map=new HashMap(); map.put("h", "hello");//向集合中添加键和值的映射 map.put("b1", new Book("Java核心技术",88)); System.out.println("集合长度:"+map.size()); map.remove("h");//通过指定的键移除键和值 //根据键获取指定的值 Book book=(Book) map.get("b1"); System.out.println("书名:"+book.getName()); //遍历Map的值的集合 for (Object temp : map.values()) { System.out.println(temp); } //清空集合 map.clear(); System.out.println("集合长度:"+map.size()); } }
泛型集合
下面代码在使用时有没有问题:
Book book=(Book) books.get(i);
List和Map添加元素时都是Object类型,在强制类型转换时容易发生异常。JDK1.5使用泛型改写了集合框架中的接口和类。
使用泛型时要加上一对“<>”,在尖括号内写上限定的数据类型。
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Test { public static void main(String[] args) { List<String> names=new ArrayList<String>(); names.add("张三");//只能添加 String 类型元素 names.get(0).substring(0);//返回的类型也是指定的类型 //Map在使用时需要同时指定键和值的类型 Map<String,String> map=new HashMap<String,String>(); map.put("h", "hello");//键和值都只能是指定的类型 } }
指定完类型后,元素就是指定的类型的元素,那这样在存数据和取数据都是指定类型,不需要类型转换。
使用泛型后,集合的遍历也更加方便,其中演示了foreach遍历Map的三种方法。
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class TestEach { public static void main(String[] args) { //List的遍历 List<Book> books=new ArrayList<Book>(); books.add(new Book("80天环游世界",34.6f)); books.add(new Book("Java核心技术",88)); books.add(new Book("Java编程思想",122)); //books.add("aaa");//去掉注释试试 for (Book book : books) { System.out.println(book.getName()); } //Map的遍历 Map<String,Book> bookMap=new HashMap<String,Book>(); bookMap.put("java", new Book("Java入门到精通",122)); bookMap.put("docker", new Book("docker入门到精通",122)); //1.遍历键获取值 for (String key : bookMap.keySet()) { Book book=bookMap.get(key); System.out.println(book.getName()); } System.out.println("=============="); //2.遍历值 for (Book book : bookMap.values()) { System.out.println(book.getName()); } System.out.println("--------------"); //3.同时遍历键和值 for (Entry<String, Book> entry : bookMap.entrySet()) { String key=entry.getKey(); Book value=entry.getValue(); System.out.println("key:"+key+" value:"+value.getName()); } } }
map.keySet() 返回的是一个 Set 集合,这也是Map的键不能重复的原因。entrySet()方法返回了Entry的集合,Entry包含了键和值。
迭代器 Iterator
迭代器用来迭代集合,常用的两个方法:hasNext()返回布尔值,判断是否存在另一个可访问的元素。next()返回要访问的下一个元素,可以指定为泛型,这样不需要类型转换。
下面看一下 List 集合和 Map 使用迭代器。
import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class TestIterator { public static void main(String[] args) { List<Book> books=new ArrayList<Book>(); books.add(new Book("80天环游世界",34.6f)); books.add(new Book("Java核心技术",88)); books.add(new Book("Java编程思想",122)); //获取迭代器 Iterator<Book> i=books.iterator(); while(i.hasNext()) { Book book=i.next(); System.out.println("图书名字:"+book.getName()); } //Map可以迭代键或值 Map<String,Book> bookMap=new HashMap<String,Book>(); bookMap.put("java", new Book("Java入门到精通",122)); bookMap.put("docker", new Book("docker入门到精通",122)); //获取键的迭代器 Iterator<String> iKey=bookMap.keySet().iterator(); while(iKey.hasNext()) { String key=iKey.next(); System.out.println(key); } //值的迭代器写法类似 Iterator<Book> iValue=bookMap.values().iterator(); while(iValue.hasNext()) { Book value=iValue.next(); System.out.println(value.getPrice()); } } }
迭代器可以和其他循环用法结合,大家可以自己尝试。
包装类
先看一下这段代码是否能编译呢?
List<int> nums=new ArrayList<int>();
编译器会提示只能写引用类型,java为每个基本数据类型都提供了引用类型。
基本类型 | 引用类型 |
---|---|
int | Integer |
double | Double |
float | Float |
byte | Byte |
long | Long |
这些引用类型赋值时可以赋值对应的基本类型
Integer i=1; Float f=2.2f;
也可以像引用类型那样初始化为null
Integer i=null;
这些包装类的方法过多,大家可以查阅文档。
欢迎将查阅到的包装类的方法发表到留言区
- 技术系列2——泛型、集合、数组
- 【JavaSE系列-基础篇6】——数组,集合,泛型宏观把控
- javase重新开始系列之集合与泛型
- 泛型系列<8>:使用泛型创建只读集合
- Java集合系列19之ConcurrentHashMap
- 快速入门系列--CLR--03泛型集合
- 深入Java集合学习系列:HashMap的实现原理
- 泛型,Map集合(非常重要)
- Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合
- Java集合中的泛型与多态问题
- Struts2系列:(19)Validation and Workflow Interceptor的区别
- Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList
- NHibernate 之 “ 值“System.Object[]”不是“”类型,不能在此泛型集合中使用。 参数名: value”
- 黑马程序员-集合与泛型集合
- Java多线程系列--【JUC集合02】- CopyOnWriteArrayList
- 集合、迭代器、增强for、集合中泛型的引入
- 【JavaSE系列-基础篇6】——泛型原始类型
- Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例
- C# List泛型集合中的GroupBy<>用法
- 使用泛型集合代替datatable作为返回值实现面向对象