目录
TreeSet练习(Comparable和Comparator接口)
接口 Collection<E>
常用的接口和实现类
公有基类方法
通用迭代器:接口 Iterator<E>
用于遍历集合,返回的元素顺序根据实现类的不同而不同
remove():删除上一次调用next()返回的元素。
List<E>接口集合
List<E>接口特有迭代器:接口 ListIterator<E>
系列表迭代器,允许程序员按任一方向遍历列表(0 ~ n,length - 1 ~ 0)、最重要的是:这个迭代期间允许修改列表(添加或删除元素)。
需要注意的是:
ListIterator迭代器的add()方法
ListIterator迭代器的add()方法,不像ArrayList的add()方法一样是追加到末尾的。而ListIterator迭代器的add()方法会将数据插入到调用next()方法后的的后面,如果未调用过next()方法直接调用add()方法,会将元素插入到0索引的前面(之前0索引的元素变成了1索引的位置)。
通过next()指定位置后,add()方法能实现插入到指定位置
List<E>集合常用的具体子类
类 | 数据结构 | 优点 | 缺点 |
Vector | 数组结构:通过删除或添加元素,会不断的new <T>[ size ];, 把旧的数组元素复制到新的数组中。 |
线程同步 | 增、删、查都慢 |
ArrayList | 数组结构:通过删除或添加元素,会不断的new <T>[ size ];, 把旧的数组元素复制到新的数组中。 |
线程不同步, 查询快 |
增、删、慢 |
LinkedList | 链表结构:在堆内存中的数据都是不规则的,通过连续添加元素会: Object(0x0) <—— (0x0) Object (0x1) <—— (0x1) Object (0x2) <—— (0x2) Object (0x3) <—— (0x3) Object (0x4) ... ...n 也就是后一个添加的元素位置会记住前一个元素的地址 |
线程不同步, 增、删速度快 |
查询慢 |
Set<E>接口集合
和接口Collection的方法一样。正常情况下存储的元素是不重复的,而List是允许重复的。
常用具体子类
类 | 数据结构 | 优点 |
HashSet | 哈希 ( 散列)结构。 使用注意:元素必须重写继承自超类Object的hashCode()和equals()方法。 重写hashCode():根据元素自身的特点计算哈希值。 重写equals():为了解决哈希值的冲突。
内部使用了HashMap |
线程不同步, 查询更快 |
LinkedHashSet | 链表 + 哈希 ( 散列)结构。 因为HashSet不保证元素添加时的顺序, 所以派生自HashSet类的LinkedHashSet就能保证元素添加时的顺序, 在添加元素时此元素位置上记住上一次添加的元素的地址,所以就能保证迭代时的顺序。 |
线程不同步, 查询更快, 存入元素的有序 |
TreeSet | 二叉树结构。 可对元素进行自定义排序方式。 基本数据类型会自然字典顺序排序(包括JDK某些实现了Comparable<T>接口)。 元素要具备比较性,需要实现Comparable<T>接口,重写int compareTo(Object o)方法, 返回数字有三个: -1(只要是负数),代表小于。 1(只要是正数),代表大于。 0,相等就不存。
如果元素不实现Comparable<T>接口,可以构造一个Comparator<T>比较器。 为了降低耦合性,可以构造一个带有Comparator<T>接口(比较器)的TreeSet, 而不是让元素实现Comparable<T>接口。
内部使用了TreeMap |
线程不同步, 可以自定义排序方式。 |
哈希(散列)算法:简单演示图
为了解决哈希值冲突,延伸出来的位置:链表结构,更确切的说哈希表 = 数组 + 链表结构
java的String类字符串hashCode算法并不是像图上一样,仅演示,看图:
双向链表演示图
因为栈内存中的对象存储是不规则的,每次查询都要从头开始查询,所以链表查询慢,增删就特别快。
Object.java的HashCode()方法代码段
-
public int hashCode() {
-
int lockWord = shadow$_monitor_;
-
final
int lockWordStateMask =
0xC0000000;
// Top 2 bits.
-
final
int lockWordStateHash =
0x80000000;
// Top 2 bits are value 2 (kStateHash).
-
final
int lockWordHashMask =
0x0FFFFFFF;
// Low 28 bits.
-
if ((lockWord & lockWordStateMask) == lockWordStateHash) {
-
return lockWord & lockWordHashMask;
-
}
-
//主要的方法,上面的代码段我不知道是干嘛用的,一般都只会执行下面的方法
-
return System.identityHashCode(
this);
//将对象的内存16进制地址转换成整数作为HashCode值
-
}
-
-
public boolean equals(Object o) {
-
return
this == o;
//只对比引用是否相同
-
}
-
-
//从这个方法知道,是对象的内存地址,通过hashCode值转换成的16进制地址
-
//而hashCode值是内存16进制地址转换成
-
public String toString() {
-
return getClass().getName() +
'@' + Integer.toHexString(hashCode());
-
}
测试一般只执行System.identityHashCode(Object);方法是否成立:
-
Object o =
new Object();
-
-
System.out.
println(
"地址 = " + o.toString());
-
System.out.
println(
"hashCode() = " + o.hashCode());
-
System.out.
println(
"toHex --> hashCode() = " + Integer.toHexString(o.hashCode()));
-
-
System.out.
println();
-
-
System.out.
println(
"identityHashCode() = " + System.identityHashCode(o));
-
System.out.
println(
"toHex --> identityHashCode() = " + Integer.toHexString(System.identityHashCode(o)));
输出:
-
地址 = java.lang.Object@
15db9742
-
hashCode() =
366712642
-
toHex --> hashCode() =
15db9742
-
-
identityHashCode() =
366712642
-
toHex --> identityHashCode() =
15db9742
所以我们未重写默认的HashCode()方法值是通过对象的内存16进制地址转换为整数而成
HashSet存储元素过程
- 调用元素的hashCode()方法得到哈希值(调用底层函数,对象内存16进制地址转成的整数)
- 通过哈希值与容器大小%取余计算出位置
- 如果此位置上没有元素则添加。如果已有元素,则调用此位置上元素的equals(Object obj)进行比较:返回true则认为是相同的元素,不覆盖。返回false则认为是不同的元素,并对此位置上延伸一个新位置出来,进行添加。(正常情况下,
返回false就要考虑减少元素的哈希算法冲突,这种情况很少发生)。
在使用Set集合前,必须重写原始类型Object的hashCode()和equals()方法。
当然,不重写也没关系,这样只能保证引用的不同而存储,引用相同而不覆盖。
什么时候可以重写?比如:为了保证对象内容数据的唯一而不重复。如下:
HashSet练习
需求:保证对学生对象数据的唯一性。相同数据的学生视为同一个人则不存。
思路:
- 利用以上HashCode值冲突原理。首先重写对象的hashCode()方法:逻辑为用内部数据计算出对象的哈希值(为了让相同数据的对象引起哈希冲突后进一步调用equals()方法比较数据是否相同)。
- 然后重写equals()方法:对比数据值是否相同,如果相同true则认为是同一个对象。
- 如果不同false则认为是不同的对象,此时就是真正的哈希值冲突了,这时候就要尽量保证哈希值算法对对象的唯一性,当然这种现象很少发生。
Student.java
-
package com.bin.demo;
-
-
public
class Student {
-
-
private String name;
-
private
int age;
-
-
Student(String name,
int age) {
-
setName(name);
-
setAge(age);
-
}
-
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
@Override
-
public int hashCode() {
//这里使用IDE自动生成的,当然也可以自定义
-
final
int prime =
31;
-
int result =
1;
-
result = prime * result + age;
-
result = prime * result + ((name ==
null) ?
0 : name.hashCode());
-
return result;
-
}
-
-
@Override
-
public boolean equals(Object obj) {
//hash值冲突相同,进一步地判断对象是否唯一
-
if (
this == obj)
-
return
true;
-
if (obj ==
null)
-
return
false;
-
if (getClass() != obj.getClass())
-
return
false;
-
Student other = (Student) obj;
//这行代码到下面是判断,名字和年龄是否相同
-
if (age != other.age)
-
return
false;
-
if (name ==
null) {
-
if (other.name !=
null)
-
return
false;
-
}
else
if (!name.equals(other.name))
-
return
false;
-
return
true;
-
}
-
-
@Override
-
public String toString() {
-
return
"Student [name=" + name +
", age=" + age +
"]";
-
}
-
-
}
Main函数
-
public
class
Main {
-
-
public static void main(String[] args) {
-
-
Set<Student> hs =
new HashSet<Student>();
-
-
hs.
add(
new Student(
"超神",
17));
-
hs.
add(
new Student(
"剑圣",
16));
-
hs.
add(
new Student(
"铠甲",
18));
-
hs.
add(
new Student(
"斌哥",
20));
-
hs.
add(
new Student(
"神龙",
20));
-
hs.
add(
new Student(
"铠甲",
18));
-
hs.
add(
new Student(
"斌哥",
20));
-
-
for (Student s : hs) {
-
System.
out.println(s.toString());
-
}
-
-
}
-
-
}
输出:
-
Student
[name=铠甲, age=18]
-
Student
[name=神龙, age=20]
-
Student
[name=超神, age=17]
-
Student
[name=剑圣, age=16]
-
Student
[name=斌哥, age=20]
这就保证了不同对象的内部数据的唯一性。
二叉树 (简单介绍)
如图所见:我们在代码实现中,大的元素放右边,小的放左边,排序就是顺序排序(从小到大)。相反则_大的放左边,小的放右变,排序就是逆序排序(从大到小)。
TreeSet练习(Comparable<E>和Comparator<E>接口)
需求:对学生进行升序排序,依据年龄大小进行升序排序。如果年龄相等则对名字进行字典顺序排序,如果名字也相等则认为是相同一个人则不存。
Student.java 需要实现Comparable接口
-
package com.bin.demo;
-
-
public
class Student implements Comparable<Student> {
-
-
private String name;
-
private
int age;
-
-
Student(String name,
int age) {
-
setName(name);
-
setAge(age);
-
}
-
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
@Override
-
public String toString() {
-
return
"Student [name=" + name +
", age=" + age +
"]";
-
}
-
-
@Override
-
public int compareTo(Student s) {
//主要条件:age,次要条件:name
-
// if (this.age > s.age) {
-
// return 1;
-
// } else if (this.age < s.age) {
-
// return -1;
-
// } else {
-
// return this.name.compareTo(s.name);
-
// }
-
int isAge =
this.age - s.age;
//相减不是大于就是小于或等于
-
return isAge ==
0 ?
this.name.compareTo(s.name) : isAge;
// 如果年龄相等,按名字排序,使用的是字符串的字典顺序。如果名字相等还是返回0不存
-
}
-
-
}
main: 如果元素不实现Comparable接口,则使用Comparator接口比较器进行比较
-
public
class
Main {
-
-
public static void main(String[] args) {
-
-
//同样可以使用比较器对:集合和元素降低耦合,这样可以构造Tree集合传入不同的排序方式
-
Comparator<Student> cpt =
new Comparator<Student>() {
-
-
@
Override
-
public
int
compare(
Student news, Student s) {
-
// if (news.getAge() > s.getAge()) {
-
// return 1;
-
// } else if (news.getAge() < s.getAge()) {
-
// return -1;
-
// } else {
-
// return news.getName().compareTo(s.getName());
-
// }
-
-
int isAge = news.getAge() - s.getAge();
//相减不是大于就是小于或者等于
-
return isAge ==
0 ? news.getName().compareTo(s.getName()) : isAge;
// 如果年龄相等则用名字进行升序排序,如果名字也相同则不存
-
}
-
};
-
-
TreeSet<Student> ts =
new TreeSet<Student>(cpt);
-
-
ts.
add(
new Student(
"超神",
17));
-
ts.
add(
new Student(
"剑圣",
16));
-
ts.
add(
new Student(
"铠甲",
18));
-
ts.
add(
new Student(
"斌哥",
20));
-
ts.
add(
new Student(
"神龙",
20));
-
ts.
add(
new Student(
"铠甲",
18));
-
ts.
add(
new Student(
"斌哥",
20));
-
-
for (Student s : ts) {
-
System.
out.println(s);
-
}
-
-
}
-
-
}
输出:
-
Student
[name=剑圣, age=16]
-
Student
[name=超神, age=17]
-
Student
[name=铠甲, age=18]
-
Student
[name=斌哥, age=20]
-
Student
[name=神龙, age=20]
使用Comparator比较器更为灵活,可以降低集合和元素之间的耦合。可以定义不同的比较器功能,对学生进行不同方式的排序。
增强For循环
增强For在JDK1.5开始出现,迭代功能就抽取出来了
Collection接口 就继承了 Iterable接口,
枚举接口Enumeration<E>迭代器,因为名称过长过时了(此接口只对Vector进行迭代)
JDK1.2后就被Iterator取代了枚举接口Enumeration<E>
-
public
class Main {
-
-
public static void main(String[] args) {
-
-
ArrayList<Integer>
list =
new ArrayList<Integer>();
-
list.add(
1);
-
list.add(
2);
-
list.add(
3);
-
list.add(
4);
-
list.add(
5);
-
Vector<Integer> v =
new Vector<Integer>(
list);
-
-
//枚举方式迭代器,只有Vector拥有获取此迭代器的方法:已过时
-
for (Enumeration<Integer> e = v.elements(); e.hasMoreElements();) {
-
System.out.println(e.nextElement());
-
}
-
-
//通用for循环
-
for (Iterator<Integer> li =
list.listIterator(); li.hasNext();) {
-
System.out.println(li.next());
-
}
-
-
//高级for循环
-
for (
int i :
list) {
-
System.out.println(i);
-
//list.add(-1); //发生并发修改异常:java.util.ConcurrentModificationException
-
}
-
-
}
-
-
}
通用For循环与增强For循环的区别:
- 增强For只能操作Collection接口的类型和数组,并且迭代期间不能操作元素。会报并发修改异常java.util.ConcurrentModificationException异常。
- 通用For循环能操作索引,并且迭代期间可以对元素进行操作。
- 所以增强For只为遍历,开发中减少代码。通用For还是比较强。
Map<K,V>接口集合
键值对的存储方式。保证键的唯一。
需要注意的方法:
- put(K key, V value): 方法,将值与键进行关联,返回的是这个键与上一次关联的值,如果上一次并没有与该键关联的值就返回null。
- remove(key): 删除该键的映射关系,并返回与该键关联的值,如果没有该键则返回null。
- keySet(): 返回Set<K>集合的键。set 支持元素移除,通过 Iterator.remove 操作可从映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
- entrySet() : 返回 Set<Map.Entry<K,V>>集合,Map.Entry是Map接口里的内部的静态接口,此方法将每个键值对封装成了一个Map.Entry<K,V>,该接口有getKey()、getValue()、setValue(V v)、等方法。通过 Iterator.remove 操作可从映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
- values(): 返回Collection<V>集合,返回的都是值。collection 支持元素移除,通过 Iterator.remove 操作可从映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
遍历时不能调用(除Iterator.remove()方法)外的添加和删除元素方法,否则会报 java.util.ConcurrentModificationException
Map集合遍历三种方式
-
package com.bin.demo;
-
-
import java.util.Collection;
-
import java.util.HashMap;
-
import java.util.Iterator;
-
import java.util.Map;
-
import java.util.Set;
-
-
public
class Main {
-
-
public
static
void main(
String[] args) {
-
-
Map<
String, Integer> m =
new HashMap<
String, Integer>();
-
m.put(
"A",
1);
-
m.put(
"B",
2);
-
m.put(
"C",
3);
-
m.put(
"D",
4);
-
m.put(
"E",
5);
-
-
// keySet()
-
Set<
String> s = m.keySet();
-
for (Iterator<
String> i = s.iterator(); i.hasNext();) {
-
String key = i.next();
-
int value = m.get(key);
-
System.out.println(
"key = " + key +
" ————> " +
"value = " + value);
-
}
// 增强 for (String s : m.keySet())
-
-
// entrySet()
-
Set<
Map.Entry<
String, Integer>> me = m.entrySet();
-
for (Iterator<
Map.Entry<
String, Integer>> i = me.iterator(); i.hasNext();) {
-
Map.Entry<
String, Integer> e = i.next();
-
String key = e.getKey();
-
int value = e.getValue();
-
System.out.println(
"key = " + key +
" ————> " +
"value = " + value);
-
}
// 增强 for (Map.Entry<String, Integer> e : m.entrySet())
-
-
// values()
-
Collection<Integer> c = m.values();
-
for (Iterator<Integer> i = c.iterator(); i.hasNext();) {
-
int value = i.next();
-
System.out.println(
"value = " + value);
-
}
// 增强 for (int value : m.values())
-
-
}
-
-
}
输出:
-
key = A ————>
value =
1
-
key = B ————>
value =
2
-
key = C ————>
value =
3
-
key = D ————>
value =
4
-
key = E ————>
value =
5
-
-
key = A ————>
value =
1
-
key = B ————>
value =
2
-
key = C ————>
value =
3
-
key = D ————>
value =
4
-
key = E ————>
value =
5
-
-
value =
1
-
value =
2
-
value =
3
-
value =
4
-
value =
5
这里用的是HashMap,是不保证有序的
Map集合常用子类
类 | 数据结构 | 优点 |
HashTable | 哈希表结构。 | 线程同步, 不允许Null键, 不允许Null值 |
HashMap | 哈希表结构。 | 线程不同步, 允许Null键, 允许Null值。 |
LinkedHashMap | 链表 + 哈希表结构。 | 线程不同步, 允许Null键, 允许Null值, 元素的插入是有序的。 |
TreeMap | 二叉树结构。 元素需要具备比较功能。键需要实现Comparable<E>接口, 如果键不实现Comparable<E>接口,需要构造一个Comparator<E>比较器。 |
线程不同步, 可以对Map集合中的键进行自定义排序。 |
HashMap练习
需求:同样是对学生进行存储,键是学生对象(有名字和年龄),值是存学生当前所在的城市,学生名字和年龄一样则视为同一个人则不存。
Student.java 覆盖equals()和hashCode()方法。
-
package com.bin.demo;
-
-
public
class Student {
-
-
private String name;
-
private
int age;
-
-
Student(String name,
int age) {
-
setName(name);
-
setAge(age);
-
}
-
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
@Override
-
public int hashCode() {
//同样需要利用哈希冲突原理,然后用equals()方法进行数据的判断是否相同
-
final
int prime =
31;
-
int result =
1;
-
result = prime * result + age;
-
result = prime * result + ((name ==
null) ?
0 : name.hashCode());
-
return result;
-
}
-
-
@Override
-
public boolean equals(Object obj) {
-
if (
this == obj)
-
return
true;
-
if (obj ==
null)
-
return
false;
-
if (getClass() != obj.getClass())
-
return
false;
-
Student other = (Student) obj;
-
if (age != other.age)
-
return
false;
-
if (name ==
null) {
-
if (other.name !=
null)
-
return
false;
-
}
else
if (!name.equals(other.name))
-
return
false;
-
return
true;
-
}
-
-
@Override
-
public String toString() {
-
return
"Student [name=" + name +
", age=" + age +
"]";
-
}
-
-
}
Main.java
-
package com.bin.demo;
-
-
import java.util.HashMap;
-
import java.util.Map;
-
-
public
class Main {
-
-
public
static
void main(
String[] args) {
-
-
Map<Student,
String> m =
new HashMap<Student,
String>();
-
m.put(
new Student(
"啊斌",
20),
"广东");
-
m.put(
new Student(
"雨烟",
19),
"广西");
-
m.put(
new Student(
"豪哥",
22),
"江苏");
-
m.put(
new Student(
"昌弟",
17),
"广西");
-
m.put(
new Student(
"贺弟",
18),
"深圳");
-
m.put(
new Student(
"益达",
23),
"北京");
-
-
m.put(
new Student(
"啊斌",
20),
"广西");
//去了广西:新的值映射到键
-
m.put(
new Student(
"雨烟",
19),
"广东");
//去了广东:新的值映射到键
-
-
for (Student s : m.keySet()) {
-
String value = m.get(s);
-
System.out.println(
"key = " + s +
" ————> 地址 = " + value);
-
}
-
-
}
-
-
}
输出:
-
key = Student [
name=益达, age=
23] ————> 地址 = 北京
-
key = Student [
name=啊斌, age=
20] ————> 地址 = 广西
-
key = Student [
name=贺弟, age=
18] ————> 地址 = 深圳
-
key = Student [
name=雨烟, age=
19] ————> 地址 = 广东
-
key = Student [
name=豪哥, age=
22] ————> 地址 = 江苏
-
key = Student [
name=昌弟, age=
17] ————> 地址 = 广西
TreeMap练习
需求:同样是对学生进行存储。键是学生对象(有名字和年龄),值是存学生当前所在的城市,学生名字和年龄一样则视为同一个人则不存。升序排序:主要条件根据年龄进行排序,次要条件年龄相同后根据名字在编码表的顺序位置进行排序。
Student.java 实现Comparable接口
-
package com.bin.demo;
-
-
public
class Student implements Comparable<Student> {
-
-
private String name;
-
private
int age;
-
-
Student(String name,
int age) {
-
setName(name);
-
setAge(age);
-
}
-
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
@Override
-
public String toString() {
-
return
"Student [name=" + name +
", age=" + age +
"]";
-
}
-
-
@Override
-
public int compareTo(Student s) {
-
// if (this.age > s.age) {
-
// return 1;
-
// } else if (this.age < s.age) {
-
// return -1;
-
// } else {
-
// return this.name.compareTo(s.name);
-
// }
-
int isAge =
this.age - s.age;
//相减不是大于就是小于或等于
-
return isAge ==
0 ?
this.name.compareTo(s.name) : isAge;
// 如果年龄相等则用名字进行升序排序,如果名字相同则不存
-
}
-
-
}
Main.java 如果元素不实现Comparable接口,可以使用Comparator接口比较器
-
package com.bin.demo;
-
-
import java.util.Comparator;
-
import java.util.Map;
-
import java.util.TreeMap;
-
-
public
class Main {
-
-
public static void main(String[] args) {
-
-
//同样可以使用比较器对:集合和元素降低耦合,这样可以构造Tree集合传入不同的排序方式
-
Comparator<Student> cpt =
new Comparator<Student>() {
-
-
@Override
-
public int compare(Student news, Student s) {
-
// if (news.getAge() > s.getAge()) {
-
// return 1;
-
// } else if (news.getAge() < s.getAge()) {
-
// return -1;
-
// } else {
-
// return news.getName().compareTo(s.getName());
-
// }
-
-
int isAge = news.getAge() - s.getAge();
//相减不是大于就是小于或者等于
-
return isAge ==
0 ? news.getName().compareTo(s.getName()) : isAge;
// 如果年龄相等则用名字进行升序排序,如果名字也相同则不存
-
}
-
};
-
-
Map<Student, String> m =
new TreeMap<Student, String>(cpt);
-
m.put(
new Student(
"啊斌",
20),
"广东");
-
m.put(
new Student(
"雨烟",
19),
"广西");
-
m.put(
new Student(
"豪哥",
22),
"江苏");
-
m.put(
new Student(
"昌弟",
17),
"广西");
-
m.put(
new Student(
"贺弟",
18),
"深圳");
-
m.put(
new Student(
"益达",
23),
"北京");
-
-
m.put(
new Student(
"啊斌",
20),
"广西");
//去了广西:新的值映射到键
-
m.put(
new Student(
"雨烟",
19),
"广东");
//去了广东:新的值映射到键
-
-
for (Student s : m.keySet()) {
-
String value = m.get(s);
-
System.out.println(
"key = " + s +
" ————> 地址 = " + value);
-
}
-
-
}
-
-
}
输出:
-
key = Student [
name=昌弟, age=
17] ————> 地址 = 广西
-
key = Student [
name=贺弟, age=
18] ————> 地址 = 深圳
-
key = Student [
name=雨烟, age=
19] ————> 地址 = 广东
-
key = Student [
name=啊斌, age=
20] ————> 地址 = 广西
-
key = Student [
name=豪哥, age=
22] ————> 地址 = 江苏
-
key = Student [
name=益达, age=
23] ————> 地址 = 北京
Comparable接口和Comparator接口比较器
对于Tree集合来说。我们比较器返回的数值,顺序排序(从小到大)和逆序排序(从大到小)都是我们自己的逻辑实现的。
上面的二叉树练习都是顺序排序,所以下面是逆序排序学生的算方法
二叉树 (简单介绍)——方便看放这
如图所见:我们在代码实现中,大的元素放右边,小的放左边,排序就是顺序排序(从小到大)。相反则_大的放左边,小的放右变,排序就是逆序排序(从大到小)。
Comparable(逆序排序)
-
@Override
-
public int compareTo(Student s) {
-
if (
this.age > s.age) {
-
return
-1;
//新元素大于旧元素,就放左边
-
}
else
if (
this.age < s.age) {
-
return
1;
//新元素小于旧元素,就放右边
-
}
else {
-
return
this.name.compareTo(s.name);
//如果相等则不存
-
}
-
-
/*旧元素 减 新元素,
-
* 返回的数据:新元素则会使用旧元素的对比(大、小)
-
* 如果大于:则把新元素放到右边(此时新元素是小的)
-
* 如果小于:则把新元素放到左边(此时新元素是大的)
-
*/
-
// int isAge = s.age - this.age; //相减不是大于就是小于或等于
-
// return isAge == 0 ? this.name.compareTo(s.name) : isAge; // 如果年龄相等则用名字进行升序排序,如果名字相同则不存
-
}
Comparator(逆序排序)
-
Comparator<Student> cpt =
new Comparator<Student>() {
-
-
@Override
-
public int compare(Student news, Student s) {
-
if (news.getAge() > s.getAge()) {
-
return -
1;
//新元素大于旧元素,就放左边
-
}
else
if (news.getAge() < s.getAge()) {
-
return
1;
//新元素小于旧元素,就放右边
-
}
else {
-
return news.getName().compareTo(s.getName());
//如果相同不存
-
}
-
-
/*旧元素 减 新元素,
-
* 返回的数据:新元素则会使用旧元素的对比(大、小)
-
* 如果大于:则把新元素放到右边(此时新元素是小的)
-
* 如果小于:则把新元素放到左边(此时新元素是大的)
-
*/
-
// int isAge = s.getAge() - news.getAge(); //相减不是大于就是小于或者等于
-
// return isAge == 0 ? news.getName().compareTo(s.getName()) : isAge; // 如果年龄相等则用名字进行升序排序,如果名字相同则不存
-
}
-
};
Collections集合工具类
- 二分查找
- 最值
- 元素的排序
- 元素的替换
- 最重要的是:可对非同步集合转成同步集合。
- 等等...
集合转数组
和Collections集合工具类无关,集合转数组是通过Collection接口中的方法:
第一个方法返回后可能根据需求还得强转,通常用第二种方法:传入一个任意类型的(除基本类型)数组,就返回这个类型的数组。
-
package com.bin.demo;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
public
class Main {
-
-
public static void main(String[] args) {
-
-
List<Integer>
list =
new ArrayList<Integer>();
-
list.add(
1);
-
list.add(
2);
-
list.add(
3);
-
-
/*
-
* 构造和集合相等长度的数组,如果构造的数组大小不合适集合的size,则会自动new相等长度的数组
-
*/
-
Integer[] arr =
list.toArray(
new Integer[
list.size()]);
//如果数组类型和集合元素类型不匹配,则发生java.lang.ArrayStoreException异常
-
-
for (
int i : arr) {
-
System.out.println(i);
-
}
-
-
}
-
-
}
-
-
-
输出:
-
1
-
2
-
3
Arrays工具类(操作数组)
- 任何类型的数组进行排序
- 二分查找
- 复制到新数组
- 替换元素
- 转换String
- 数组转集合,注意事项:(转换后不支持对数组的增删)(如果数组元素是基本类型数据,则直接把数组引用当作集合元素。如果数组元素是引用类型数据,则把数组的每个元素当作集合元素存储)
- 等等...
数组转集合注意
-
package com.bin.demo;
-
-
import java.util.Arrays;
-
import java.util.List;
-
-
public
class Main {
-
-
public static void main(String[] args) {
-
-
int[] arr = {
1,
2,
3,
4,
5};
-
List<
int[]> aList = Arrays.asList(arr);
-
// aList.add(new int[] {-1}); //异常: java.lang.UnsupportedOperationException
-
System.out.println(aList.size());
//打印长度
-
-
}
-
-
}
-
-
输出:
-
1
转载:https://blog.csdn.net/qq_42470947/article/details/104764941