List接口
/**
* list接口继承了Collection接口,可在Collection基础之上添加一些新方法
* */
public class Demo01List {
public static void main(String[] args) {
//使用多态创建集合对象
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
//遍历集合
System.out.println(list);
System.out.println("----------");
//在指定索引位置添加元素
list.add(1, "马龙");
System.out.println(list);
System.out.println("----------");
//更改指定索引位置元素
String setStr = list.set(0, "刘国梁");
System.out.println(list);
System.out.println("----------");
//移出指定索引位置元素
String removeEle = list.remove(3);
System.out.println(list);
System.out.println("----------");
//list集合带有索引
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
ArrayList类
- ArrayList接口继承了List集合常用的方法
- 优点:因为底层时数组,所以查询效率较高
- 缺点:每次添加一个元素,都是通过调用System.arraycopy()方法复制一个数组,将新元素添加进去
- ‘注意:此实现不是同步的,即多线程
LinkedList类
- LinkedList 集合同样也是继承了List集合
- 优点:因为底层使用链表实现,所以增删效率较高
- 缺点:查询效率低
- 注意:此实现不是同步的,即多线程
/**
* LinkedList 集合同样也是继承了List集合
* 优点:因为底层使用链表实现,所以增删效率较高
* 缺点:查询效率低
* 注意:此实现不是同步的,即多线程
* * */
public class Demo01LinkedList {
public static void main(String[] args) {
//创建一个LinkedList集合
LinkedList<String> linked = new LinkedList<>();
linked.add("a");
linked.add("b");
linked.add("c");
linked.add("d");
System.out.println(linked);
System.out.println("-------------------");
//向集合头添加元素
linked.push("头部元素");
linked.addFirst("头部元素2");
System.out.println(linked);
System.out.println("-------------------");
//向集合尾部添加元素
linked.addLast("尾部元素1");
System.out.println(linked);
System.out.println("--------------------");
//获取头部元素
String firstEle = linked.getFirst();
System.out.println(firstEle);
System.out.println(" ");
//获取尾部元素
String lastEle = linked.getLast();
System.out.println(lastEle);
System.out.println("-------------------");
//删除并返回头部元素
String removeEle = linked.removeFirst();
String pop = linked.pop();
//删除并返回尾部元素
String removeElel = linked.removeLast();
System.out.println(linked);
}
}
Vector类
- Vector集合继承了List接口
- 优点:Vector集合底层时数组
- 注意:Vector集合是同步的,即单线程
Set接口
- Set接口继承了Collection接口
- 注意:Set中集合没有索引,和Collection接口中方法相同
- Set集合中不存储重复值元素
HashSet接口
- HashSet接口继承了Set接口
- 不允许存储重复元素
- 无索引
- 是一个无序的集合
- 底层是一个哈希表结构,查询效率高
- 注意:HashSet中集合不保证顺序的持久性
- 底层不是同步的,即单线程
hashCode()方法
- 哈希值:是一个十进制的整数,由系统随机给出,是一个对象的逻辑地址,不是实际的物理地址
- 在Object类中有一个方法可以获取哈希值
- public native int hashCode()
- native代表是本地方法
public class Person extends Object {
//在创建String类对象时才重写此方法
@Override
public int hashCode() {
return 1;
}
}
/**
* 哈希值:是一个十进制的整数,由系统随机给出,是一个对象的逻辑地址,不是实际的物理地址
* 在Object类中有一个方法可以获取哈希值
* public native int hashCode()
* native代表是本地方法
* */
public class Demo02HashCode {
public static void main(String[] args) {
//Person继承了Object类,所以可以使用hashCode()方法
Person p1 = new Person();
int h1 = p1.hashCode();
System.out.println(h1);
Person p2 = new Person();
int h2 = p2.hashCode();
System.out.println(h2);
/**
* toString() 方法源码
* return getClass().getName + "@" + Integer.toHexString(hashCode());
*
* */
System.out.println(p1);
System.out.println(p2);
/**
* 重写String类中的hashCode()方法
*
* */
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println("重地" + s1.hashCode());
System.out.println("通话" + s2.hashCode());
}
}
哈希表
哈希表结构图解
- 在jdk1.8之前哈希表结构:数组+链表
- 在jdk1.8之后哈希表结构:数组+红黑树
- 当链表的节点个数大于8个时会变成红黑树
Set集合不存储重复元素原理
- 当调用add()方法向集合中添加元素时,add()方法会调用元素的hashCode()方法和equals()方法;hashCode()方法判断是否有哈希冲突,equals()判断是否有重复元素
- Set集合存储不重复元素前提:存储的元素必须重写hashCode()方法和equals()方法
- 注意:八大基本元素的包装类已经重写了hashCode()方法和equals()方法
HashSet存储自定义元素
- 存储自定义元素时,若要存储重复元素要重写hashCode()方法和equals()方法
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = 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;
}
}
/**
* 哈希表存储不重复元素
* 八大基本类型的包装类已经重写了hashCode()方法和equals()方法
* 这里要自定义类且存储不重复元素要重写hashCode()方法和equals()方法
* 注意:年龄和姓名相同时看作相同元素
* */
public class Demo01HashCode {
public static void main(String[] args) {
HashSet<Person> set = new HashSet<>();
//创建对象
Person p1 = new Person("小王", 18);
Person p2 = new Person("小王", 18);
Person p3 = new Person("小张", 19);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set); //过没有重写俩个方法则三个对象都可以添加到set集合中
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1.equals(p2)); //false若没有重写此方法比较的时俩个对象的地址值
}
}
LinkedHashSet集合
- 底层是一个哈希表+链表,(多了一条链表记录元素的存储顺序)保证元素有序
/**
* LinkedHashSet
* 底层是一个哈希表+链表,(多了一条链表记录元素的存储顺序)保证元素有序
* * */
public class Demo01LinkedHashSet {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
hashSet.add("小王");
hashSet.add("小王");
hashSet.add("校长");
System.out.println(hashSet); //无序 不存储重复元素
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("小张");
linkedHashSet.add("小张");
linkedHashSet.add("小王");
System.out.println(linkedHashSet); //有序 不存储重复元素
}
}
排序
使用Collections接口中的方法对集合进行排序
- 注意:被排序的元素必须实现Comparable接口,重写compareTo方法
- 规定:自己-参数 :升序,否则降序
案例一
public class Person implements Comparable<Person>{
private String name;
private int age;
@Override
public int compareTo(Person person) {
return this.getAge() - person.getAge(); //升序
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + 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;
}
}
public class Demo01Collection {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
//第二个参数为可变参数,即可以添加任意个元素
//向集合中添加元素
Collections.addAll(list, "小张", "小王", "往");
System.out.println(list);
//打乱集合中的顺序
Collections.shuffle(list);
System.out.println(list);
//自定义类元素排序
Person p1 = new Person("小张", 10);
Person p2 = new Person("小王", 19);
Person p3 = new Person("小周", 8);
ArrayList<Person> list1 = new ArrayList<>();
list1.add(p1);
list1.add(p2);
list1.add(p3);
//方法一按照年龄升序排序
Collections.sort(list1, (o1, o2)->o1.getAge() - o2.getAge()); //用此方法在Person类中可以不用实现Comparable接口
System.out.println(list1);
/**
* 方法二:也可在在Person类创建时继承Comparable接口
* 在其中重写compareTo()方法
*
* */
}
案例二
/**
* 使用Collections接口中的方法对集合进行排序
* 注意:被排序的元素必须实现Comparable接口,重写compareTo方法
* 规定
* 自己-参数 :升序
* 否则降序
* */
public class Demo01Sort {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(2);
list.add(1);
list.add(3);
list.add(6);
System.out.println(list);
//使用sort方法排序,默认升序
Collections.sort(list);
System.out.println(list);
//(方法一)重写compareTo()方法降序排列
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer integer, Integer t1) {
return t1 - integer;
}
});
//(方法二)使用lambda表达式
Collections.sort(list, (Integer t1, Integer t2)->t1-t2);
System.out.println(list);
}
}
Comparetor和Comparable区别
- Comparable是集合内部比较,自己(this)和参数作比较,自己需要实现comparable接口,重写compareTo()方法
- Comparetor在集合外部比较相当于找一个第三方的裁判比较
Map集合
- Collection集合称为单列集合,Map集合称为双列集合
使用键值对遍历集合图解
- 使用键值对遍历map集合
- 首先使用map集合中的entrySet(0方法获取entry对象且存储在set集合中
- 遍历set集合,获取每一个entry对象
- 过entry集合中的getKey()和getValue()方法获取每个entry对象的键值对
- 1、首先获取键集合set
- 2、遍历键集合set使用get方法获取值
/**
* 遍历map集合
*
* */
public class Demo02KeySet {
public static void main(String[] args) {
show();
}
/**
* 方式一:通过键值对方式
* 1、首先获取键集合set
* 2、遍历键集合set使用get方法获取值
* */
public static void show() {
//创建map集合
Map<String, Integer> map = new HashMap<>();
map.put("张继科", 180);
map.put("樊振东", 180);
map.put("许昕", 189);
/**
* 通过键值对遍历集合
* */
//获取set集合
Set<String> set = map.keySet();
for (String key : set) {
int value = map.get(key);
System.out.println(key + "=" + value);
}
/**
* 也可用迭代器遍历集合
* */
}
}
使用EntrySet遍历集合
/**
* 使用键值对遍历map集合
* 1、首先使用map集合中的entrySet(0方法获取entry对象且存储在set集合中
* 2、遍历set集合,获取每一个entry对象
* 3、通过entry集合中的getKey()和getValue()方法获取每个entry对象的键值对
* * */
public class Demo03EntrySet {
public static void main(String[] args) {
//创建一个map集合(多态)
Map<String, Integer> map = new HashMap<>();
map.put("马龙", 175);
map.put("樊振东", 170);
map.put("张继科", 180);
//创建set集合存储entry对象
Set<Map.Entry<String, Integer>> set = map.entrySet();
//遍历set集合
for (Map.Entry<String, Integer> e : set) {
String key = e.getKey();
Integer value = e.getValue();
System.out.println(key + "=" + value);
}
}
}
HashMap集合
- hashMap底层实现是哈希表
- jdk1.8之前:数组+单向链表
- jdk1.8之后:数组+单向链表/红黑树(当链表节点个数大于8个时为红黑树)
- 是一个无序的集合
/**
* HashMap集合常用一些方法
* hashMap底层实现是哈希表
* jdk1.8之前:数组+单向链表
* jdk1.8之后:数组+单向链表/红黑树(当链表节点个数大于8个时为红黑树)
* 是一个无序的集合
* LinkedHashMao集合:
* 底层实现是:哈希表+单向链表(巴奥赵正得迭代的顺序)
* 是一个有序的集合
* */
public class Demo01HashMap {
public static void main(String[] args) {
//创建一个map集合(多态)
Map<String, Integer> map = new HashMap<>();
/**
* 添加元素
* */
map.put("马龙", 175);
map.put("樊振东", 170);
map.put("张继科", 180);
System.out.println(map);
Integer hight = map.put("马龙", 178); //这里接收相同的键被替代的值,若键在map集合中未出现,则返回null
System.out.println(map);
/**
* 删除键值对
* */
Integer h = map.remove("樊振东");
System.out.println(map);
/**
* 获取键对应的值
* */
Integer h2 = map.get("张继科"); //这里要用包装类型变量接收,因为当键不存在时返回null
System.out.println(h2);
/**
* 判断集合是否包含键 或值
* */
boolean flag = map.containsKey("马龙");
boolean flag2 = map.containsValue("180");
System.out.println(flag);
System.out.println(flag2);
}
}