集合
文章目录
集合概述
-
数组:存放一组相同数据类型的数据结构
- 数组的特点:
- 数组一旦创建,其长度不能改变
- 一个数组只能存放一种数据类型的数据
- 数组的特点:
-
集合:是一种存放多种数据类型的数据结构
- 集合的特点:
- 集合的长度是可变的
- 对存放数据的数据类型无限制
- 集合的特点:
定义
- 在Java中,使用一些类来描述集合,这样的类我们称之为集合类,集合类的对象就是一个集合
- 集合类 obj = new 集合类;
学习任务
- 了解Java中的集合类及其继承关系
- 创建集合类的对象(创建集合)
- 向集合中添加元素
- 获取集合中的元素(获取单个元素)
- 遍历集合(一次取出集合中的所有元素)
集合大的分类
-
Collection(单值集合)(接口):是所有单值集合的父接口
- List(接口):集合中的元素是有序可重复的
- ArrayList
- LinkedList
- Vector
- Set(接口):集合中的元素是无序不可重复的
- HashSet
- TreeSet
单值集合:ArrayList、LinkedList、Vector
- List(接口):集合中的元素是有序可重复的
-
Map(键值对集合)(接口):是所有键值对集合的父接口
- AbstractMap(抽象类)
- HashMap
- Hashtable
- Properties
键值对集合:HashMap、Hashtable、Properties
- AbstractMap(抽象类)
集合中的各种区别
-
Collection 和Collections 的区别(接口/帮助类)
- Collection 是一个接口,是所有单值集合的父接口
- Collections 是一个帮助类,这个类中提供了很多对集合进行各种操作的静态方法
-
List 接口 和 Set 接口的区别(有序可重复/无序不可重复)
- List接口和Set接口都是Collection接口的子接口
- List中的元素是有序可重复的
- Set中的元素是无序不可重复的
-
ArrayList 和 LinkedList的区别(数组/链表)
-
ArrayList 和 LinkedList都是List 接口的实现类,其元素都是有序可重复的
-
ArrayList 中的元素是基于数组的实现
- 查询元素:顺序查找,速度快
- 添加元素:尾部添加,速度较快
- 插入元素:会涉及到内存中元素的依次移动,速度较慢
-
LinkedList中的元素是基于链表的实现
- 查询元素:需要根据前一个元素获取到后一个元素的地址依次查找,速度相对较慢
- 添加元素:尾部添加,但是有地址的操作,速度相对较慢
- 插入元素:无须依次移动元素,速度较快
链表特点:不必事先估计存储空间,可随机访问任一元素,所需空间和线性表的长度成正比
-
-
ArrayList 和 Vector 的区别(线程非安全,速度快/线程安全)
- ArrayList 和 Vector 都是基于数组的存储;Vector 实现了同步是线程安全的(多线程中用),而ArrayList 是线程非安全的,但是ArrayList 的存储效率较高。
-
HashSet 和 TreeSet的区别(Hash码散列存储/树形存储)
- 两者都是Set接口的实现类,其元素都是无序不可重复的;区别在于元素存储方式不同,HashSet是按照hash码散列存储,TreeSet树形存储
-
HashMap 和 Hashtable 的区别(null,线程)
-
两者都是Map 接口的实现类,都表示键值对集合。
-
HashMap 中允许一个null键和多个null值,但Hashtable中不允许使用null作为key或者value;
-
HashMap 未实现同步,是线程非安全的;Hashtable实现了同步,是线程安全的
Propreties键、值都为String类型
-
键值对
key value null "aaa"
"bbb"
3 1 null “a” null
-
Collection的常用方法及迭代器
collection接口常用方法
-
创建集合
ArrayList list = new ArrayList();
-
boolean add(E e):将指定的元素添加到集合中
list.add("abc"); list.add("wahaha"); list.add(3); list.add(true);
-
int size():获取当前集合中存放元素的个数
int len = list.size(); System.out.println("len-->" + len);
-
boolean addALL(Collection c):将参数指定的集合(list)中的所有元素全部添加到当前集合(b)
b.addAll(list);
-
void clear():清空当前集合中的所有元素
list.clear();
-
boolean contains(Object o):检查当前集合中是否包含参数指定的元素
boolean flag1 = list.contains("wahaha");
-
boolean containsAll (Collection<?> c):检查当前集合中是否包含参数指定的集合中的元素
boolean flag2 = b.containsAll(list);
-
boolean isEmpty():判断当前集合是否为null
boolean flag3 = list.isEmpty();
-
boolean remove(Object o):从当前集合中移除参数指定的元素
boolean flag4 = list.remove("wahaha");
-
boolean removeALL(Collection<?> c):从集合b中移除集合(list)中的所有元素
boolean flag5 = b.removeAll(list);
-
Object [] toArray():将当前集合的元素全部取出,存放到一个Object类型的数组中
Object [] obj = list.toArray(); for(Object o : obj){ System.out.println(o); }
List接口常用用法
- List集合,因为其中元素的存储是有序的,所有我们可以用索引来标注每个元素,List集合中索引的范围【0~list.size()-1】
-
void add(int index, E element):将第二个参数指定的元素插入到list集合中索引为第一个参数的位置
list.add(3, "e");
-
E get(int index):获取当前集合中指定索引处的元素
Object o1 = list.get(2);
-
E remove(int index):移除指定索引处的元素
Object o2 = list.remove(3);
-
boolean remove(Object o) :移除集合里的指定元素
集合里面存放的为封装类型,普通类型要转为封装类型
boolean flag1 = list.remove( new Integer(3) );
-
int indexOf(Object o):元素第一次出现的索引
int n = list.indexOf("a");
-
int lastIndexOf(Object o):元素最后一次出现的索引
int m = list.lastIndexOf("a");
-
遍历集合
Object [] obj = list.toArray(); for(Object o : obj){ System.out.println(o); } for(int i = 0; i < list.size(); i++){ Object obj2 = list.get(i); System.out.println("obj2-->" + obj2); }
Iterator接口
- 专为Collection提供的元素遍历迭代器
- 可以迭代List集合 和 Set集合
不仅可以遍历集合还可以对元素进行操作
-
通过集合获取迭代器
Iterator it = list.iterator();
-
判断是否存在元素
System.out.println(it.hasNext());
-
获取元素
Object e = it.next();
-
移除元素
it.remove();
-
使用Iterator迭代器遍历输出集合
while(it.hasNext()){ Object e2 = it.next(); System.out.println("e2-->" + e2); }
ListIterator接口
-
只可以迭代List集合
-
ListIterator可以实现List集合的倒序遍历
-
Iterator迭代器只可以删除最后一次获取的元素
-
ListIterator迭代器不仅可以移除,还可以修改,还可以在当前元素之后添加一个元素
ArrayList list = new ArrayList(); list.add("abc"); list.add("wahaha"); list.add(3); list.add(true); list.add('a'); ListIterator lit = list.listIterator(); //正序遍历输出 while(lit.hasNext()){ Object e1 = lit.next(); System.out.println("e1-->" + e1); // lit.set("hehe");//修改 // lit.add("hehehe");//添加 lit.remove();//移除 } //倒序遍历输出 while(lit.hasPrevious()){ Object e2 = lit.previous(); System.out.println("e2~~~>" + e2); }
Map集合常用方法及视图(迭代)、枚举
-
创建Map集合的三种常用类–创建键值对集合
HashMap map = new HashMap(); Hashtable table = new Hashtable(); Properties p = new Properties();//key 和value只能是String类型
-
添加元素
map.put("a", 123); map.put(1,"abc"); map.put(null, null);//table的key不能为null,编译无错,运行有错 map.put("hehe", null);
-
获取集合中的键值对个数
int len = map.size();
-
根据key移除一个键值对
map.remove("hehe"); map.clear();//清空
-
修改键值对,调用put方法,如果对应的key存在,则可以通过key修改value
map.put(1, "wahaha");
-
通过key获取value
Object v1 = map.get(1);
-
根据key判断value是否存在
Boolean flag1 = map.containsKey("hehe");
-
参数制定value的值是否存在
boolean flag2 = map.containsValue("wahaha");
-
遍历键值对集合(keySet视图:只视图key)主键视图
Set set = map.keySet();//map转为Set集合 Iterator it = set.iterator();//迭代主键 while(it.hasNext()) { Object k = it.next(); Object v = map.get(k); System.out.println(k + "--------"+ v); }
-
遍历键值对集合(entrySet键值对视图:视图key-value一对)
// 10.遍历键值对集合(entrySet键值对视图:视图key-value一对)
//将缉拿对打包为一个整体转换为set集合
Set set2 = map.entrySet();
//获得迭代器
Iterator it2 = set2.iterator();
//通过迭代器判断集合中是否存在元素
while (it2.hasNext()) {
//获取元素并强转为Map.Entry内部类
Map.Entry e = (Map.Entry) it2.next();
//Map.Entry内部类的两个方法分别得到key和value
Object k = e.getKey();
Object v = e.getValue();
System.out.println(k + "~~~~" + v);
}
-
枚举(Enumeration)
Enumeration en = table.keys(); while(en.hasMoreElements()){ Object k = en.nextElement(); Object v = table.get(k); System.out.println( k + "=====" + v ); }
Properties
-
//Properties的键和值只能存放String类型,所以一半用来存储属性信息 Properties p = new Properties(); p.setProperty("uname", "zs"); p.setProperty("age", "18"); System.out.println( p.size()); String v = p.getProperty("uname"); System.out.println(v); Properties p2 = System.getProperties();//获取系统的属性 Enumeration en = p.keys(); while(en.hasMoreElements()){ String k = (String)en.nextElement(); String v1 = p.getProperty(k); System.out.println( k + "\t" + v1); }
-
public static void main(String[] args) throws IOException { Properties p = new Properties(); File f = new File("D:/code/user.properties"); //此抽象类是表示字节输入流的所以类的超类 InputStream is = new FileInputStream(f); p.load(is);//从输入流中读取属性列表 //打印出所读取的属性列表 Enumeration en = p.keys(); while(en.hasMoreElements()){ String k = (String)en.nextElement(); String v = p.getProperty(k); System.out.println(k+"\t"+v); } //用户输入 Scanner sc = new Scanner(System.in); System.out.println("请输入用户名:"); String uname = sc.next(); System.out.println("请输入密码:"); String pwd = sc.next(); //修改、添加 p.setProperty("admin", "88888"); p.setProperty(uname , pwd ); //store():将p中的内容写出到文件中 OutputStream os = new FileOutputStream(f); p.store(os, "this is 备注信息"); }
ArrayList | HashSet | HashMap | Hashtable | |
---|---|---|---|---|
创建对象 | new ArrayList(); | new HashSet(); | new HashMap(); | new Hashtable |
添加元素 | boolean add(E e) | boolean add(E e) | V put(K key,V value) | V put(K key,V value) |
插入元素 | void add(int index, E element) | |||
移除元素 | boolean remove(Object o) | boolean remove(Object o) | remove(Object key) | remove(Object key) |
遍历集合 |
-
遍历ArrayList
Object [] obj = list.toArray(); for(Object o : obj){ System.out.println(o); } //迭代器 Terator it = list.itratoe(); while( it.hasNext()){ Object o = it.next(); System.out.println(o); }
-
遍历HashSet
Object [] obj = set.toArray(); for(Object o : obj){ System.out.println(o); } //迭代器 Terator it = set.itratoe(); while( it.hasNext()){ Object o = it.next(); System.out.println(o); }
-
遍历HashMap
//9.遍历键值对集合(keySet视图:只视图key) Set set = map.keySet(); Iterator it = set.iterator(); while(it.hasNext()){ Object k = it.next(); Object v = map.get(k); System.out.println(k+"---"+v); } //10.遍历键值对集合(entrySet键值对视图:视图key-value一对) Set set2 = map.entrySet(); Iterator it2 = set2.iterator(); while( it2.hasNext() ){ Map.Entry e = (Map.Entry)it2.next(); Object k = e.getKey(); Object v = e.getValue(); System.out.println(k+"~~~~"+v); }
-
遍历Hashtable
//9.遍历键值对集合(keySet视图:只视图key) Set set = table.keySet(); Iterator it = set.iterator(); while(it.hasNext()){ Object k = it.next(); Object v = table.get(k); System.out.println(k+"---"+v); }
二叉树
- 二叉树由各种节点组成
- 特点:
- 每个节点都可以有左字节点,右子节点
- 每个节点都有一个值
- 排序—插入数据:
- 小,相同的放左边,大的放右边
- 排序—遍历(左序、中序、右序)
- 左序:中间的数遍历后放在左边
- 中序:中间的数遍历后放在中间
- 右序:中间的数遍历后放在右边
public class Node {
public Node leftNode;
public Node rightNode;
public Object value;
public void add(Object v){
if(null == value){
value = v;
}else{
if((Integer)v-((Integer)value) <= 0){
if(null == leftNode){
leftNode = new Node();
}
leftNode.add(v);
}else{
if(null == rightNode){
rightNode = new Node();
}
rightNode.add(v);
}
}
}
public List<Object> values(){
List<Object> values = new ArrayList<Object>();
if(null != leftNode)
values.addAll(leftNode.values());
values.add(value);
if (null != rightNode)
values.addAll(rightNode.values());
return values;
}
public static void main(String[] args) {
int randoms[] = new int[] { 67, 7, 30, 73, 10, 0, 78, 81, 10, 74 };
Node roots = new Node();
for(int n : randoms){
roots.add(n);
}
System.out.println(roots.values());
}
}
聚合操作
-
使用lambda表达式
public class TestAggregate { public static void main(String[] args) { Random r = new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 10; i++) { heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100))); } System.out.println("初始化集合后的数据 (最后一个数据重复):"); System.out.println(heros); //传统方式 Collections.sort(heros,new Comparator<Hero>() { @Override public int compare(Hero o1, Hero o2) { return (int) (o2.hp-o1.hp); } }); Hero hero = heros.get(2); System.out.println("通过传统方式找出来的hp第三高的英雄名称是:" + hero.name); //聚合方式 String name =heros .stream() .sorted((h1,h2)->h1.hp>h2.hp?-1:1) .skip(2) .map(h->h.getName()) .findFirst() .get(); System.out.println("通过聚合操作找出来的hp第三高的英雄名称是:" + name); } }