Java基础—集合
一、概述
Java中的集合框架主要分为两大派别:Collection 和 Map —— 位于util包下
类的基础关系图如下(图片来自百度)
常用:
List——有序可重复
Set——无序不可重复
Map——key-value键值对的形式
完整家谱:
/
常用API可以查阅JDK API(IDEA中structure视图查看)
二、基本方法使用
基本的增删改查的方法,请自行依据API进行测试与练习。
list基本方法(ArrayList)
添加方法是:.add(e);
获取方法是:.get(index);
包含方法是:contains(Object o)
删除方法是:.remove(index); 按照索引删除; .remove(Object o); 按照元素内容删除;
其它常用方法与实例参见:http://www.cnblogs.com/epeter/p/5648026.html (完整内容请参见API)
set基本方法(HashSet)
添加方法是:.add(e);
删除方法是:.remove(Object o);
map基本方法(HashMap)
添加方法是:put(K key, V value)
;
删除方法是:remove(Object key);
获取方法是:value:get(key);
包含的方法:containsKey(key) containsValue(value)
其它常用方法参见:http://www.cnblogs.com/lwlxqlccc/p/6143887.html
注意:
若使用如下的多态的形式定义容器,请注意是否合理:
此例多态中c不能使用ArrayList的新增方法,也即是:多态不能使用新增方法!
三、遍历集合
ArrayList——主要存在2种方式,foreach(与普通for类似);iterator迭代器遍历
public static void main(String[] args) {
List<String> list = new ArrayList<>();//JDK7新特性
list.add("aa");
list.add("bb");
list.add("cc"); //普通for循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//foreach循环
for (String s : list) {
System.out.println(s);
}
//迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
//类似 Map<String, String> map = new HashMap<>();的泛型省略写法是7之后的新特性
Java中的迭代器 iterator:对 collection 进行迭代的迭代器。
通过集合的 .iterator()方法获取到迭代器后便可以进行迭代的操作,如果有删除的操作,请使用 Iterator而不是foreach
迭代器的介绍,参见:http://www.cnblogs.com/xujian2014/p/5846128.html
HashSet——主要也是以上两种方式,foreach(实质与iterator有关,只是写法不同)与iterator
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("aa");
set.add("bb");
set.add("cc"); //foreach遍历
for (String s : set) {
System.out.println(s);
}
//迭代器遍历
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
} }
HashMap——主要存在四种遍历方式,通过keySet遍历;通过enterSet遍历;单独遍历key或者value;通过迭代器遍历entry
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("k1", "v1");
map.put("k2", "v2"); System.out.println("=================keySet");
//通过keySet二次遍历 --慢且无效率
for (String key : map.keySet()) {
System.out.println("key为"+key+" value为"+map.get(key));
}
System.out.println("=================entrySet");
//最常见的通过enterSet遍历 --推荐
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key为"+entry.getKey()+" value为"+entry.getValue());
}
System.out.println("=================keys");
//单独遍历keys或者values(只需要其中一个的情况)
for (String key : map.keySet()) {
System.out.println(key);
}
System.out.println("=================values");
for (String value : map.values()) {
System.out.println(value);
}
System.out.println("=================iterator");
//使用迭代器iterator,通过entrySet遍历
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println("key为"+entry.getKey()+" value为"+entry.getValue());
}
}
完整介绍与相关性能分析等,参见:http://www.cnblogs.com/leskang/p/6031282.html
更新:list中存放的是对象的时候,里面真正放的是对象的引用的复制品(副本),但是这个副本也是指向这个对象的。[注意有序可重复和无序不可重复]
详细可以参见:http://m.blog.csdn.net/article/details?id=23520263
四、集合比较与排序
先简单介绍一下即将用到的compareTo()方法:
此方法接收一个同类型的参数,当调用的对象比传入的对象大时,返回正数,否则返回负数(相等返回0),一个简单的 例子如下:
@Override
public int compareTo(Object o) {
return (this.getAge() < ((Student) o).getAge() ? -1 :
(this.getAge() == ((Student) o).getAge() ? 0 : 1));
}
由于Integer与String等常用类都实现了此方法,所以我们可以很愉快的使用它们当我们需要的时候而不必处处都进行重写。
一般来说,基本类型使用> < ==等进行比较!,一般来说可以自己使用三目运算符实现,也可以使用相应包装类的比较方法(原理一样)!
关于此方法几种写法的探讨,给出网友博文参考:http://blog.csdn.net/u013591605/article/details/75267629
1.内排序——实体类实现Comparable接口
只需要集合中的实体类实现此接口重写CompareTo()方法,然后调用Collections工具类的sort方法即可
实体类:
package com.jiangbei.test.sort; /**
* 学生实体类
* 作者: Administrator
* 日期: 2017/9/13
**/
public class Student implements Comparable<Student>{
private Integer age;
private String name; public Student() {
} public Student(Integer age, String name) {
this.age = age;
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
} @Override
public int compareTo(Student s) {
// return (this.getAge() < ((Student) o).getAge() ? -1 :
// (this.getAge() == ((Student) o).getAge() ? 0 : 1));
return this.getAge().compareTo(s.getAge());
}
}
测试类:
public static void main(String[] args) {
Student s1 = new Student(10, "小明");
Student s2 = new Student(18, "小张");
Student s3 = new Student(15, "小红"); List<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3); System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
2.外排序——排序的类定义Comparato
实体类还是纯洁的实体类,没有任何污染;只是在排序的地方(Collections.sort里需要传入一个Compartor)
实体类:
package com.jiangbei.test.sort; /**
* 学生实体类
* 作者: Administrator
* 日期: 2017/9/13
**/
public class Student{
private Integer age;
private String name; public Student() {
} public Student(Integer age, String name) {
this.age = age;
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
} }
排序测试:
package com.jiangbei.test.sort; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; /**
* 集合比较测试类
* 作者: Administrator
* 日期: 2017/9/13
**/
public class ListSortTest{ public static void main(String[] args) {
Student s1 = new Student(10, "小明");
Student s2 = new Student(18, "小张");
Student s3 = new Student(15, "小红"); List<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3); System.out.println(list);
Collections.sort(list, comparator);
System.out.println(list);
}
// 当然可以在sort方法里通过匿名内部类的形式实现此排序
static Comparator<Student> comparator = new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return s1.getAge() > s2.getAge()? 1 : (s1.getAge() == s2.getAge()? 0 : -1);
}
}; }
关于Collections工具类的其它常见用法,参见:http://blog.csdn.net/wangshuang1631/article/details/53200764
五、重要概念——equals()和hashCode()
想要弄明白hashCode的作用,必须要先知道Java中的集合。
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。这里就引出一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上,初学者可以简单理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。简而言之,在集合查找时,hashcode能大大降低对象比较次数,提高查找效率!
Java对象的eqauls方法和hashCode方法是这样规定的:
1、equals相等(相同)的对象必须具有相等的哈希码(或者散列码)。
2、如果两个对象的hashCode相同,它们并不一定相同。
所以说,我们如果重写了equals方法,一定要重写hasCode,以保证上述规定的逻辑正确性。
一般而言,存进list,set中的对象类型的元素需要重写 equals、hashCode()方法才能使用去重等功能!
如何重写?
1.equals()方法是object方法,代码如下:
public boolean equals(Object obj) {
return (this == obj);
}
当然,实际使用中不可能使用这样的版本,这里举出一个重写的例子:
public boolean equals(Object obj) {
if(obj == null)
return false;
if(this == obj){
return true;
}
if (obj instanceof Person) {
Person other = (Person) obj;
return (p.name).equals(this.name);
}
return false;
2.hsahCode()方法,这里主要出现多的地方是集合里元素的排列问题
此方式主要返回对象的hashCode值(int类型的)
内容引用自:http://www.cnblogs.com/Qian123/p/5703507.html
对于如何实际重写两个方法,请参见:http://blog.csdn.net/zzg1229059735/article/details/51498310
Java基础—集合的更多相关文章
- JAVA基础-集合(二)
一.Map整体结构体系 Map是集合的另一大派系,与Collection派系不同的是Map集合是以键值对儿的形式存储在集合的.两个键为映射关系,其中第一个键为主键(主键是唯一的不可重复),第二个键为v ...
- Java基础-集合的嵌套
Java基础-集合的嵌套 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.静态导入 静态导入是在JDK1.5后的新特性,可以减少开发的代码量,但是实际用处是很一般,静态导入的标准 ...
- Java基础——集合框架
Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...
- java基础---集合(1)
一. 基本概念 集合.数组都是对多个数据进行存储操作的结构,简称Java容器 数组:长度确定,类型确定,对于添加.删除.插入等操作效率不高,元素有序可重复 Java中集合框架顶层框架是:java.ut ...
- Java基础——集合源码解析 List List 接口
今天我们来学习集合的第一大体系 List. List 是一个接口,定义了一组元素是有序的.可重复的集合. List 继承自 Collection,较之 Collection,List 还添加了以下操作 ...
- java基础集合简介Set(三)中
今天主要说夏set集合,每天抽出一个小时总结下,生活会更加美好! --< java.util >-- Set接口: 数据结构:数据的存储方式: Set接口中的方法和Collection中方 ...
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- 十七、Java基础---------集合框架之Map
前两篇文章中介绍了Collection框架,今天来介绍一下Map集合,并用综合事例来演示. Map<K,V> Map<K,V>:Map存储的是键值对形式的元素,它的每一个元素, ...
- 十六、Java基础---------集合框架之Set
写在前面的话,这篇文章在昨天就写好了,今天打开的时候一不小心将第二天的文章粘贴到了这篇文章,很不幸的是除了标题之外依然面目全非,今天带着沉痛的心情再来写这篇文章! 上篇文章介绍了Collection体 ...
随机推荐
- linux下yum安装指定的mysql版本
因为直接使用yum安装的mysql会是默认版本5.1的版本 但是有的同学不满足又想要其他版本的怎么办呢? 曾时候我来提供一种方案(仅供参考): 我们可以使用rpm包来进行指定mysql版本的安装, ...
- Linux查看系统当前字符集
常用的命令展示 参考当前环境的字符集 方法一: cat /etc/sysconfig/i18n [ssh客户端工具最好也是utf-8,保持一致] 方法二:echo $LANG 设置当前环境的字符集 方 ...
- September 15th 2017 Week 37th Friday
First I need your hand, then forever can begin. 我需要牵着你的手,才能告诉你什么是永远. If you want to shake hands with ...
- Chrome新发现
昨晚写代码的时候惊喜的发现Chrome中能直接使用一些ES6的语法: let, const, 箭头函数等已经能直接使用. 酷酷的. 另外我的Chrome版本还是比较旧的,并不需要最新版本.
- 囧啊!!时间戳转化为时间出错php
最近写了一个api,测试也没发现啥问题.可是上线之后发现有时api的返回结果不正确.为什么呢? 调我接口的同学给了两个调用示例,理论上两个的结果应该一致,实际结果却不一致. api调用带了一个时间戳参 ...
- Tomcat6的相关配置
1. Tomcat无安装部署: 本文windows用的是win7,ubuntu用的是12.04 LTS,tomcat版本是1.6 1.1. windows上的tomcat无安装部署 1.1.1. 确认 ...
- 4-4 R语言函数 tapply
#对向量的子集进行操作 #tapply(参数):tapply(向量,因子/因子列表,函数/函数名) > x <- c(rnorm(5),runif(5),rnorm(5,1)) > ...
- iOS 开源库系列 Aspects核心源码分析---面向切面编程之疯狂的 Aspects
Aspects的源码学习,我学到的有几下几点 Objective-C Runtime 理解OC的消息分发机制 KVO中的指针交换技术 Block 在内存中的数据结构 const 的修饰区别 block ...
- Loj #2256. 「SNOI2017」英雄联盟
题目 我就是个丝薄 如果要用\(dp_i\)表示凑出\(i\)的最小花费显然不可能的 之后大力猜想能凑出来的状态不会很多,我的暴力也告诉我不是很多,好像也确实不多的样子,大概\(4e4\)左右 但是我 ...
- 解决osx下 ssh: connect to host localhost port 22: Connection refused
解决办法: 终端下执行:sudo systmesetup -setremotelogin on