javaSE_day16
- 集合
- 1. Collection常用方法
- 2. 遍历集合
- 3. List-ArrayList(数组)
- 3.1 常用方法:
- 3.2 和集合相关的方法:
- 4. 集合和数组的相互转换
- 5. 集合排序的两种方式
- 练习:实现ArrayList
- List集合
- ArrayList、LinkedList 和 Vector
- 实现LinkedList
- Set集合
- HashSet 和 TreeSet
- Map集合
- 1. 常用方法
- 2. 遍历Map结合的三种方法
- 3. HashMap和HashTable区别
- 集合总结
集合
1. Collection常用方法
2. 遍历集合
- 第一种方法: 增强for循环
for(String str : coll){
System.out.println(str);
} - 第二种方法: 迭代器
Iterator it = coll.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
} - 第三种方法: lambda表达式
coll.forEach(a->System.out.println(a));
3. List-ArrayList(数组)
3.1 常用方法:
3.2 和集合相关的方法:
4. 集合和数组的相互转换
- 集合转换成数组 toArray()
- 数组转换成集合 Arrays.asList()
5. 集合排序的两种方式
- 方法一: 实现Comparator接口,重写compare方法
在外部排序,改变默认排序规则 - 方法二: 实现Comparable接口,重写compareTo方法
嵌入到排序的类中
Arrays.sort(数组排序)
Collections.sort(集合排序)
练习: 按照学生成绩排序
- 定义Student类
两个变量:name,score
方法:get、set、toString、构造方法 - 定义集合,3个student对象,添加到集合
- 使用sort方法排序,排序是指定排序规则
- 输出排序后的集合
练习:实现ArrayList
package cn.tedu.collection;
import java.util.Arrays;
public class MyArray {
private int size;//表示集合的元素个数
private String[] strArray;
//1.定义无参的构造方法 默认给数组10个
public MyArray() {
strArray = new String[10];
}
//2.定义一个带参的构造方法
public MyArray(int length) {
strArray = new String[10];
}
//3.判断元素的个数和数组的长度之间的关系 size>=strArray 扩容
//添加元素
public void add(String str) {
if (size>strArray.length) {
grow();
}
strArray[size] = str;
size++;
}
//4.规则:数组长度的一半(如果数组长度为1 ,扩容应该是+1)
public void grow() {
if (strArray.length<=1) {
strArray = Arrays.copyOf(strArray, strArray.length+1);
}else {
strArray = Arrays.copyOf(strArray, strArray.length+strArray.length/2);
}
}
//5.判断元素的个数和数组的长度之间的关系 size>=strArray 扩容
// 当前的数组元素后移
// 插入元素
public void add(int index,String str) {
if (size>=strArray.length) {
grow();
}
//{1,2,3} index = 1 3-index
//{1,1,2,3}
System.arraycopy(strArray, index, strArray, index+1, size-index);
strArray[index] = str;
size++;
}
//6.当前的数组元素前移
public void remove(int index) {
System.arraycopy(strArray, index+1, strArray, index, size-index-1);
size--;
}
//7.修改
public void set(int index,String str) {
strArray[index] = str;
}
//8.获取元素
public String get(int index) {
return strArray[index];
}
//9.返回集合中的元素个数
public int size() {
return size;
}
public static void main(String[] args) {
MyArray myArray = new MyArray();
myArray.add("hello");
myArray.add("abc");
myArray.add("admin");
myArray.remove(1);
myArray.set(1, "admin!!!");
myArray.add(1,"222");
for (int i = 0; i < myArray.size(); i++) {
System.out.println(myArray.get(i));
}
}
}
List集合
ArrayList、LinkedList 和 Vector
- LinkedList和ArrayList都是线程不安全的
- Vector是线程安全的
实现LinkedList
package cn.tedu.Li;
public class LinkList {
private int size = 0; // 节点个数
private Node first; // 第一个节点
private Node last; // 最后一个节点
//无参构造方法
public LinkList() { }
//添加元素
public void add(String str) {
Node node = new Node(null, str, null); // 以尾部元素为前继节点创建一个新节点
if (size == 0) {
// 如果空链表的情况:同时更新first节点也为需要插入的节点。(也就是说:该节点既是头节点first也是尾节点last)
this.first = node;
this.last = node;
}else {
this.last.next = node;
node.prev = this.last;
this.last = node;
}
size++; // 更新链表大小和修改次数,插入完毕
}
//插入
public void add(int index, String str) {
//最后 this.add()
if (index==size) {
this.add(str);
return;
}
Node node = new Node(null, str, null);
if (index==0) {
//在链表的最前边
node.next = this.first.prev;
this.first.prev = node;
this.first = node;
}else {
//中间
Node node1 = this.getNode(index);
node1.prev.next = node;
node.prev = node.prev;
node.next = node1;
node1.prev = node;
}
size++;
}
// 获取指定位置的节点
private Node getNode(int index) {
Node node = this.first;
for (int i = 0; i <index; i++) {
node = node.next;
}
return node;
}
//删除
public void remove(int index) {
//删除第一个
if (index==0) {
this.first.next.prev = null;
this.first = this.first.next;
}
//删除最后一个
else if (index==size-1) {
this.last.prev.next = null;
this.last = this.last.prev;
}
//删除中间的
else {
Node node = this.getNode(index);
node.prev.next = node.next;
node.next.prev = node.prev;
}
size--;
}
//返回节点的内容
public String get(int index){
return this.getNode(index).data;
}
// 返回元素个数
public int size(){
return size;
}
//利用节点存储数据
private class Node {
Node prev; // 上一个节点
String data; // 元素
Node next; // 下一个节点
public Node(Node prev, String data, Node next) {
super();
this.prev = prev;
this.data = data;
this.next = next;
}
}
}
Set集合
不重复
先判断hashCode(); 若相同,还要判断equals方法,如果返回true,则表示一个对象,否则是不同对象
HashSet 和 TreeSet
- HashSet基于HashMap的实现
- HashSet的元素是map中的key。
- TreeSet的元素必须是有排序规则的对象,否则会运行时异常
Map集合
1. 常用方法
2. 遍历Map结合的三种方法
3. HashMap和HashTable区别
- 线程是否安全: HashTable安全, HashMap不安全的
- key/value:HashTable不可以为null, HashMap可以为null
练习:
接收键盘输入一个字符串,统计字符的个数。
集合总结
HashMap | HashSet |
实现了Map接口 | 实现了Set接口 |
存储键值对 | 仅存储对象 |
使用put()方法将元素放入map中 | 使用add()方法将元素放入set中 |
使用键对象来计算hashcode值 | 使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false |
比较快,因为是使用唯一的键来获取对象 | HashSet较HashMap来说比较慢 |
有序 | 线程安全 | 原理及特性 | 线程同步 | 适用场景 | |
Map | 无序 | 否 | 1.是一个接口 2.主要用于存储键值对(key-value的形式),不允许键重复,允许值重复 | 否 | |
HashMap | 无序 | 否 | 1. 原理:实现了Map接口的实现类,基于hashing原理,通过put()和get()方法存储和获取对象。将键值对传递给put()方法时,调用见对象的hashCode()方法计算hashCode,然后找到bucket位置来存储键值对象。当获取对象时,通过equals()方法找到正确的键值对,然后返回值对象。2. HashMap的遍历速度和他的容量有关。3. HashMap底层是基于数组+链表。4. “碰撞”:当两个不同的键对象的hashcode相同时, 它们会储存在同一个bucket位置的链表中,Entry(包含有键值对的Map.Entry对象)会存储在链表中。使用键对象的equals()方法用来找到键值对。 | 否 | 在Map 中插入、删除和定位元素,HashMap 是最好的选择 |
TreeMap | 有序 | 否 | 1. 实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。2. 对元素进行整体的自然排序,需要元素对应的类实现。3. 如果需要给某个TreeSet对象单独制定比较规则,则使用Comparable;若不指定,则使用Comparable进行整体的自然排序 | 否 | 自然顺序或自定义顺序遍历键,那么TreeMap会更好 |
set | 无序 | 否 | Set的集合里不允许对象有重复的值 | 否 | |
HashSet | 无序 | 否 | 1. 实现了Set接口,不允许集合中有重复的值。2. 在对象存储在HashSet之前要确保对象重写equals()和hashCode()方法,比较对象的值是否相等,以确保Set中没有存储相等的对象,若不重写,则使用该方法的默认实现。 | 否 | |
List | 有序 | 否 | 1list是接口。List允许有重复,它对集合中的对象进行索引。通过下标对指定位置上的元素进行操作 | 否 | 快速插入和删除 |
LinkList | 有序 | 否 | 基于节点(Node)来实现的。利用节点来存储数据以及维系链表之间每一个节点的关系。内存空间不连续。 | 否 | 便于增删改 |
ArrayList | 有序 | 否 | 1. 用数组实现的List的实现类2. 内存空间连续 | 否 | 便于查询 |
Vector | 有序 | 是 | 1.依靠数组来存储数据,每次扩容默认增加一倍。 | 是 | 快速查找 |