07 - JavaSE之容器
本章宗旨:1136 -- 1个图 1个类 3个知识点 6个接口
容器
J2SDK 所提供的容器 API 位于 java.util 包内。
容器 API 的类图如下:
Collection 接口的子接口分为:Set接口(包含 HashSet类) + List接口(包含LinkedList 类和 ArrayLis t类)
Map接口:包含HashMap类
Set接口和List接口定义了不同的数据存储方式:
- Set 中的数据对象没有顺序并且不可以重复。
- List 中的数据对象有顺序并且可以重复。
- Map接口定义了存储“键(key)——值(value)映射”的方法。
Collection接口
- Collection接口中所定义的方法:
int size()
boolean isEmpty()
void clear()
boolean contains(Object element)
boolean add(Object element)
boolean remove(Object element)
Iterator iterator()
boolean containsALL(Collection c)
boolean addALL(Collection c)
boolean removeALL(Collection c)
boolean retainALL(Collection c)
Object[] toArray()
举例1:
import java.util.*;
public class Test {
public static void main(String[] args) {
Collection c = new ArrayList();
// 可以放入不同类型的对象
c.add("Hello");
c.add(new String("World"));
c.add(new Integer(100));
System.out.println(c.size());
System.out.println(c);
}
}
// 3
// [Hello, World, 100]
举例2:
import java.util.*;
public class Test {
public static void main(String[] args) {
Collection c = new HashSet();
c.add("Hello");
c.add(new String("World"));
c.add(new Integer(100));
// 可以删除因为HashSet重写了equals方法。
c.remove("Hello");
c.remove(new Integer(100));
System.out.println(c.size());
System.out.println(c);
}
}
// 1
// [100]
- 容器类对象在调用 remove,contains 等方法时需要比较对象是否相等,这会涉及到对象类型的 equals 方法和 hashcode 方法;对于自定义的类型,需要重写 equals 和 hashCode 方法以实现自定义的对象相等规则。
- 相等的对象应该具有相同的 hash codes,但是 hashCode 只在这个对象作为索引、键值的时候使用此方法,其他时候虽然不用,但是还是要重写此方法,至于重写此方法的具体实现可以随便写(比如我直接返回0也是可以的)。
Iterator 接口
所有实现了 Collection 接口的容器类都有一个 iterator 方法,这个方法返回一个实现了 Iterator 接口的对象。
这个 Iterator 对象称为迭代器,用以方便的实现对容器内的元素的遍历操作。
Iterator 接口定义了如下方法:
boolean hasNext(); // 判断游标右边是否有元素
Object next(); // 返回游标右边的元素并移动游标到下一个位置
void remove(); // 删除游标左边的元素,在执行完next之后,该操作只能执行一次
举例1:
import java.util.*;
public class Test {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("Hello");
c.add(new String("World"));
c.add(new Integer(100));
Iterator i = c.iterator();
while(i.hasNext()) {
System.out.println(i.next());
}
}
}
- Iterator 对象的 remove 方法是在迭代过程中删除元素的唯一的安全方法。(不能使用 Collection 对象的 remove 方法,因为管家Iterator 对象在迭代过程中会将元素上锁,外人无法访问。)
import java.util.*;
public class Test {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("Hello");
c.add(new String("World"));
c.add(new Integer(100));
Iterator i = c.iterator();
for(Iterator i = c.iterator(); i.hasNext(); ) {
if(i.next().equals(100)) {
i.remove();
}
}
System.out.println(c); // [Hello, World]
}
}
补充:JDK1.5 增强的 for 循环
- 增强的 for 循环对于遍历 array 或者 Collection 的时候相当简便。
import java.util.*;
public class EnhancedFor {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
for(int i : arr) {
System.out.println(i);
}
Collection c = new ArrayList();
c.add(new String("aaa"));
c.add(new String("bbb"));
c.add(new String("ccc"));
for(Object o : c) {
System.out.println(o);
}
}
}
- 增强型 for 循环的缺陷:(除了简单遍历外,不建议使用增强 for 循环)
- 对于数组:不能方便的访问下标值。
- 对于 Iterator ,不能方便的删除集合中特定的元素。
Set 接口
- Set接口是 Collection 的子接口,Set 接口没有提供额外的方法,实现Set接口的容器类中的元素是没有顺序的,而且不可以重复。
- Set容器可以与数学中的“集合”概念相对应。
- JDK API中所提供的Set容器类有HashSet,TreeSet等。
举例1:
public static void main(String[] args) {
Set s = new HashSet();
s.add("hello");
s.add("world");
s.add("world"); // 相同的元素不会被加入,类似数学的集合概念
System.out.println(s); // [hello, world]
}
举例2:
public static void main(String[] args) {
Set s1 = new HashSet();
Set s2 = new HashSet();
s1.add("a");s1.add("b");s1.add("c");
s2.add("d");s2.add("a");s2.add("b");
Set sn = new HashSet(s1);
Set su = new HashSet(s1);
sn.retainAll(s2);
su.addAll(s2);
System.out.println(sn); // [a, b]
System.out.println(su); // [d, a, c, b]
}
List 接口
- List接口是 Collection的 子接口,实现List接口的容器类中的元素是有顺序的,而且可以重复。
- List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
- JAVA SDK提供的List容器类有 ArrayList,LinkedList等。
Object get(int index) // 返回index位置的元素
// 返回值为Object,表示set替换掉的元素,返回出来
Object set(int index, Object element)
void add(int index, Object element)
Object remove(Object o)
int indexOf(Object o)
int lastIndexOf(Object o)
举例:
List l1 = new LinkedList();
for(int i=0; i<6; i++) {
li.add("a" + i);
} // [a0, a1, a2, a3, a4, a5, a6]
System.out.print((String)l1.get(2) + " "); // a2
System.out.println(li.indexOf("a3")); // 3
li.remove(1);
System.out.println(l1); // [a0, a2, a3, a4, a5, a6]
List 常用算法(Collections类)
- Collections类提供了一些静态方法实现了基于List容器的常用算法。
void sort(List) // 对List容器内的元素排序
void shuffle(List) // 对List容器内的元素进行随机排列
void reverse(List) // 对List容器内的元素进行逆序排列
void fill(List, Object) // 用特定的List元素列表填充整个List容器
void copy(List dest, List src)
void binarySearch(List, Object) // 对于顺序的List容器,采用二分法查找指定对象
Comparable 接口
问题:上面的算法根据什么确定容器中对象的“大小”顺序?
其实,所有可以排序的类都实现了 java.lang.Comparable 接口,Comparable河口中只有一个方法:
public int compareTo(Object obj);
该方法:
返回0表示: this == obj
返回正数表示:this > obj
返回负数表示:this < obj
实现 Comparable接口的类通过实现 compareTo 方法从而确定该类对象的排序方法。
PS:我们可以看到 compareTo 方法的参数类型是 Object 类型的,意味着如果我只想比较两只猫的话,我扔一只狗也是可以的,这就没意义了,所以在之后的 JDK 里面,将 Object 类型统一改为 泛型,这样在传入的时候就统一了比较的对象。
改写 Name 类,让其实现 Comparable 接口:
class Name implements comparable {
//...
public int compareTo(Object o) {
Name n = new (Name)o;
int lastCmp = lastName.compareTo(n.lastName); // 先比较姓氏大小
return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName)); // 再比较名字大小
}
}
改写了 compareTo 方法,相当于改写了Collections类的排序算法,至于如何排序,由你决定!
如何选择数据结构?
- 衡量标准:读的效率和写的效率(如字符串逆序操作)
- Array 读快写慢(写的慢,需要另开辟数组)
- Linked 写快读慢(写的快,还需要改变指针指向)
- Hash 介于两者之间
Map接口
- 实现Map接口的类用来存储 “键值对”
- Map接口的实现类有 HashMap 和 TreeMap
- Map类中存储的键值对通过键来标识,所以键的值不能重复
Object put(Object key, Object value) // 返回值为 Object,是替换掉的 value
Object get(Object key)
Object remove(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
void putAll(Map m)
void clear()
举例1:
import java.util.*;
public class Test {
public static void main(String[] args) {
Map m1 = new HashMap();
Map m2 = new HashMap();
m1.put("one", new Integer(1));
m1.put("two", new Integer(2));
m1.put("three", new Integer(3));
m2.put("A", new Integer(1));
m2.put("B", new Integer(2));
System.out.println(m1.size());
System.out.println(m1.containsKey("one"));
System.out.println(m2.containsValue(new Integer(2)));
if(m1.containsKey("two")) {
int i = ((Integer) m1.get("two")).intValue();
System.out.println(i);
}
Map m3 = new HashMap(m1);
m3.putAll(m2);
System.out.println(m3);
}
}
举例2:
import java.util.*;
public class Test {
private static final Integer ONE = new Integer(1);
public static void main(String[] args) {
Map m = new HashMap();
for(int i=0; i<args.length; i++) {
Integer freq = (Integer) m.get(args[i]);
m.put(args[i], freq == null ? ONE : new Integer(freq.intValue() + 1));
}
System.out.println(m);
}
}
// java Test 77 88 99 99 99
// {77=1, 88=1, 99=3}
Auto-boxing/unboxing
- 在合适的时机自动打包/解包
- 自动将基础类型转换成对象
- 自动将对象转换成基础类型
import java.util.*;
public class Test {
private static final int ONE = 1;
public static void main(String[] args) {
Map m = new HashMap();
for(int i=0; i<args.length; i++) {
int freq = ((Integer) m.get(args[i]) == null ? 0 : (Integer) m.get(args[i]));
m.put(args[i], freq == 0 ? ONE : freq + 1);
}
System.out.println(m);
}
}
泛型
- 起因
- JDK1.4之前类型不明确,装入集合的类型都被当做 Object 对待,从而失去了其本身的实际类型。
- 从集合中取出元素时需要转型,效率低,容易产生错误。
- 解决办法
- 在定义集合的时候定义集合中对象的类型
import java.util.*;
public class Test {
public static void main(String[] args) {
Collection<String> c = new HashSet<String>();
c.add("aaa"); c.add("bbb"); c.add("ccc");
for(Iterator<String> i = c.iterator(); i.hasNext(); ) {
System.out.println(i.next());
}
}
}
// aaa ccc bbb
总结
1136:一个图,一个类,三个知识点,六个接口
07 - JavaSE之容器的更多相关文章
- Linux 容器的使用
Linux 容器的使用 Linux 容器在 v2.6.29版本之后就加入到内核之中了, 之前虽然也听说过, 但一直没有太留心, 一直使用 KVM 来创建虚拟机. 直至最近 Docker 大出风头, 才 ...
- docker容器资源限制:限制容器对内存/CPU的访问
目录 一.系统环境 二.前言 三.docker对于CPU和内存的限制 3.1 限制容器对内存的访问 3.2 限制容器对CPU的访问 一.系统环境 服务器版本 docker软件版本 CPU架构 Cent ...
- 马士兵Java视频教程 —— 学习顺序
第一部分:J2se学习视频内容包括: 尚学堂科技_马士兵_JAVA视频教程_JDK5.0_下载-安装-配置 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第01章_JAVA简介_源代码_及重 ...
- [转载]马士兵Java视频教程 —— 学习顺序
书(Java核心编程)+视频..这样学感觉比较好.. 原文地址:马士兵Java视频教程 —— 学习顺序作者:习惯 第一部分:J2se学习视频内容包括: 尚学堂科技_马士兵_JAVA视频教程_JDK5. ...
- JavaDay1(上)
Java learning_Day1(上) 一切准备工作已经做好,虽然自己之前也零零碎碎学了一些Java的基础知识,貌似现在忘得差不多了,趁寒假契机从头开始学习吧 本人学习视频用的是马士兵的,也在这里 ...
- javaSE基础07
javaSE基础07 一.static静态修饰符 用了static修饰的变量就会变成共享的属性,只会初始化一次,在内存中只存在一个,并且每个对象都可以访问,存放在方法区(数据共享区) 1.1 stat ...
- JavaSE学习总结第07天_面向对象2
07.01 成员变量和局部变量的区别 1.在类中的位置不同 成员变量 类中方法外 局部变量 方法内或者方法声明上 2.在内存中的位置不同 成员变量 堆内存 局部变量 栈内存 3 ...
- Docker容器学习与分享07
Docker容器网络 在分享06中学完了bridge网络,接着学习none网络和host网络. Docker在安装时会在host上默认创建三个网络,分别是bridge.host.null. [root ...
- spring boot 尚桂谷学习笔记07 嵌入式容器 ---Web
------配置嵌入式servlet容器------ springboot 默认使用的是嵌入的Servlet(tomcat)容器 问题? 1)如何定制修改Servlet容器的相关配置: 1.修改和se ...
随机推荐
- Redis集群master选举时长测试
在一台物理机上启动6个Redis实例,组成3主3从集群,端口号依次为:1379 ~ 1384,端口号1379.1380和1384三个为master,端口1379的进程ID为17620.现将进程1762 ...
- command not found Operation not permitted
mysql -uroot -p 报错误:command not found 因为苹果在OS X 10.11中引入的SIP特性使得即使加了sudo(也就是具有root权限)也无法修改系统级的目录,其中 ...
- C(m,n)算法
排列组合:C(m,n),m为给定数列,n为要从数列m中取元素的数量,GetResult()获取所有不重复的组合. public class MathCombination<T> { Lis ...
- [ 9.13 ]CF每日一题系列—— 340A GCD & LCM
Description: [ 着实比较羞愧,都想着去暴力,把算法(方法)也忘了] A只涂x,2x,3x……,B只涂y,2y,3y……问你A和B共同涂的墙的个数 Solution: 就是求x和y的lcm ...
- AngularJS 路由 resolve属性
当路由切换的时候,被路由的页面中的元素(标签)就会立马显示出来,同时,数据会被准备好并呈现出来.但是注意,数据和元素并不是同步的,在没有任何设置的情况下,AngularJS默认先呈现出元素,而后再呈现 ...
- 有关VS报错Files的值XXX
从网上下载了一个实例来学习,但是运行的时候报错:Files的值(后面跟一堆符号,看不懂), 环境:安装了易赛通加密软件(估计可能跟这个加密软件有关系了) 解决方案:找到程序根目录的obj/Debug/ ...
- [NewCode 4] 替换空格
题目描述 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 最直接的方式, ...
- 质量能量等效的泛化--物理学定律方程与等效原理的对应关系 Generalization of Mass-Energy Equivalence--Corresponding Relations between Equations of Physical Laws and Equiva
前文所述,质能方程E=Mc^2可知质能等效,即可设计实验,使得实验无法分辨是何者变化. 泛化:所有的物理学定律方程都可看作方程两边的概念是等效的. 举几个栗子: 例一:F=ma--伊萨克爵士的代表作. ...
- JS学习笔记9_JSON
1.JSON概述 JavaScript Object Natation,js对象表示法,(像XML一样)是一种数据格式,它与js有相同的语法形式 P.S.一点小历史:JSON之父是道格拉斯,<J ...
- WPF Bitmap转成Imagesource的性能优化
之前有个需求是在WPF中生成二维码,用的是QRCoder. QRCoder生成的是Bitmap,在wpf中需要转换成ImageSource才能显示. 之前的转换方式是: IntPtr hBitmap ...