Java集合
List集合
- ArrayList集合
1.ArrayList是List接口的一个实现类,它是程序中最常见的一种集合类;
2.在ArrayList内部封装了一个数组对象,初始长度缺省为10,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来重新容纳这些元素,因此可以将ArrayList集合看作一个长度可变的数组;
3.ArrayList集合类的大部分方法都是从父类Collection和List继承过来的,其中add()方法和get()方法用于实现元素的添加和读取。
4.ArrayList集合的内部使用一个数组来保存元素。在删除元素时,会将被删除元素之后的元素都向前移一个位置以填补空位;而在用add(intindex, Object element)方法添加元素时,是把元素插入index指向的位置,先把该位置的元素以及后续元素都向后移一个位置,如果超出数组的容量,会创建更大的新数组。因为增删元素会导致大量的内存操作,所以效率低,但ArrayList集合允许通过索引随机的访问元素,查询效率高。
5.集合和数组一样,索引的取值范围是从0开始,到size-1为止(size是集合的长度),不能超出此范围,否则会引发异常。add(Objecto)方法是把元素添加到集合的尾部,而add(intindex, Object o)是把元素添加到由索引index指定的位置。
- LinkedList
LinkedList集合
1.List接口的另一个实现类LinkedList,克服了ArrayList集合在增删元素时效率较低的局限性。但是LinkedList集合的查询效率低(不支持随机访问),要查询第n个元素,必须从第一个元素开始,逐一的向后遍历,直到第n个元素。
2.该集合内部维护了一个双向链表,链表中的每个元素都通过对象引用来记住它的前一个元素和后一个元素,从而将所有的元素彼此连接起来。
3.当插入一个新元素时,只需要修改元素之间的引用关系即可,删除一个节点也是如此。
4.LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。
Map集合
- HashMap和Hashtable实现类
HashMap和Hashtable都是Map接口的典型实现类,它们之间的关系完全类似于Arraylist和Vecctor的关系。
区别:
Hashtable是线程安全的,HashMap是线程不安全的,所以HashMap比Hashtable的性能高一点。
Hashtable不允许使用null作为key和value;但HashMap可以使用null作为key或value。
HashMap和Hashtable判断两个value相等的标准:只要两个对象通过equals方法比较返回true即可。
- LinkedHashMap实现类
LinkedHashMap实现类使用链表来维护key-value的次序,可以记住键值对的插入顺序。
- SoetedMap接口和TreeMap实现类
TreeMap存储key-value键值对时,需要根据key对节点进行排序。TreeMap可以保证所有的key-value对处于有序状态。也有两种排序方式:
自然排序:TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则抛出ClassCastException异常。
定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。不需要Map的key实现Comparable接口。
Set集合
Set集合的特點是内部元素不重复
-
HashSet
使用HashSet特点:内部元素无序,唯一
~~~~~~~~~~~~~~~~~~Test1~~~~~~~~~~~~~~~~~~~~~~~~~~
// 创建一个HashSet
HashSet<String> set = new HashSet<>();
// 添加
set.add("er");
set.add("er");
set.add("ghg");
set.add("e3");
set.add("t5w3");
set.add("y645");
set.add("f4e");
System.out.println(set);
//结果:[f4e, ghg, t5w3, y645, er, e3]
~~~~~~~~~~~~~~~~~~Test2~~~~~~~~~~~~~~~~~~~~~~~~~~
package jowney.com.lib;
/**
* 重写hashCode与equles
* hashCode是第一道门槛儿,如果没有重复的hashCode那么就
* 直接把元素添加进去。如果有相同的那么就执行equles方法
*/
//通过重写对象类的 equals 和 hashCode 去重:
public class Student {
private String name;
private String age;
private Integer cardNumber;
public Student(String name, String age, Integer cardNumber) {
this.name = name;
this.age = age;
this.cardNumber = cardNumber;
}
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
return true;
}
@Override
public String toString() {
return "姓名:"+name+" 年齡:"+age;
}
}
// 创建一个HashSet 添加6个人
HashSet<Person> set = new HashSet<>();
set.add(new Student("張四","22",422132132));
set.add(new Student("張五","23",433213213));
set.add(new Student("張六","24",442132132));
set.add(new Student("張七","25",453333333));
set.add(new Student("張八","26",462313322));
Iterator<Person> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//打印结果:姓名:張四 年齡:22
//(hashCode和equles的作用完美的体现出来了)
- LinkedHashSet
LinkedHashSet 的特点:1、有序怎么存就怎么取出来 2、元素唯一
//添加字符串:
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("l");
set.add("w");
set.add("w");
set.add("a");
set.add("n");
set.add("g");
System.out.println(set);
//输入一个字符串,去掉其中重复字符
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
LinkedHashSet<Character> set = new LinkedHashSet<>();
char[] charArray = string.toCharArray();
for (int i = 0; i < charArray.length; i++) {
set.add(charArray[i]);
}
System.out.println(set);
//利用set集合 去除ArrayList集合中的重复元素(操作原ArrayList)
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("a");
arrayList.add("b");
arrayList.add("b");
arrayList.add("c");
arrayList.add("c");
LinkedHashSet<String> set = new LinkedHashSet<>();
// 将list所有元素 扔到set中去重
set.addAll(arrayList);
// 清空原arrayList
arrayList.clear();
arrayList.addAll(set);
System.out.println(arrayList);
- TreeSet
TreeSet内部实现是红黑二叉树
二叉查找树
二叉树遍历
特点:1、排序 2、元素唯一
~~~~~~~~~~~~~~test1~~~~~~~~~~~~~~~~~~
// 创建一个TreeSet
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(1);
treeSet.add(13);
treeSet.add(1);
treeSet.add(3);
treeSet.add(2);
for (Integer integer : treeSet) {
System.out.println(integer);
}
第一种:TreeSet 排序,需要实现Comparable这个接口,编写排序规则,系统就会按规则来排序。
注意:hashCode和equals在treeSet中不起作用
compareTo方法:
返回0时 , 表示此元素与集合中元素重复,不插入
返回1时 , 表示放在二叉树的右边(大节点放右边)
返回-1时 ,表示放在二叉树的左边
TreeSet 按二叉树保存的:
要保存的数比根小 放在我的左边
要保存的数比根大 放在我的右边
要保存的数与根一样大 不存
打印 按从小到大输出 (升序)
使用TreeSet排序的步骤:
1.让TreeSet集合中保存的对象 实现Comparable接口
2.实现compareTo方法
3.在compareTo方法中实现你要排序的规则
// 创建TreeSet集合
TreeSet<Worker> treeSet = new TreeSet<>();
treeSet.add(new Worker("sxm0", 11));
treeSet.add(new Worker("sxm01", 11));
treeSet.add(new Worker("sxm5", 12));
treeSet.add(new Worker("sxm4", 12));
treeSet.add(new Worker("sxm2", 15));
treeSet.add(new Worker("sxm3", 14));
for (Worker worker : treeSet) {
System.out.println(worker);
}
// 实现Comparable接口
public class Worker extends Person implements Comparable<Worker>{
public Worker() {
super();
}
public Worker(String name, int age) {
super(name, age);
}
// 实现接口中的唯一方法
// 按年龄比较
@Override
public int compareTo(Worker o) {
return this.getAge() - o.getAge();
}
// 按姓名比较
@Override
public int compareTo(Worker o) {
return this.getName().compareTo(o.getName());
}
// 主要条件 按年龄 次要条件 姓名
@Override
public int compareTo(Worker o) {
if(this.getAge() == o.getAge()) {
return this.getName().compareTo(o.getName());
}
return this.getAge() - o.getAge();
}
// 主要比字符串长度 然后比年龄 最后比字符串
@Override
public int compareTo(Worker o) {
if (this.getName().length() == o.getName().length()) {
if(this.getAge() == o.getAge()) {
return this.getName().compareTo(o.getName());
}
return this.getAge() - o.getAge();
}
return this.getName().length() - o.getName().length();
}
}
第二种:Comparator比较器
使用比较器来排序步骤:
1.创建一个类 实现Comparator
2.实现接口中的方法 并编写 比较的规则
3.把该类的对象 传入 TreeSet集合中
//比较字符串长度:
TreeSet<String> set = new TreeSet<>(new StringLengthCompareImpl());
set.add("asd");
set.add("asde");
set.add("asdef");
set.add("a");
set.add("asa");
System.out.println(set);
// 创建一个比较器类 专门来做字符串的长度比较
class StringLengthCompareImpl implements Comparator<String>{
// 比较规则
// 主要比 字符串长度
// 次要比 字符串
@Override
public int compare(String o1, String o2) {
int num = o1.length() - o2.length();
return num == 0 ? o1.compareTo(o2) : num;
}
}
//保留重复的字符串:
TreeSet<String> set = new TreeSet<>(new KeepStringImpl());
set.add("asd");
set.add("asde");
set.add("asdef");
set.add("a");
set.add("asd");
System.out.println(set);
// 保留重复的字符串 比较器
class KeepStringImpl implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
int length = o1.length() - o2.length();
int num = length == 0 ? o1.compareTo(o2) : length;
// 返回 1 或 -1
return num == 0 ? 1 : num;
}
}