java基础_day14

一 List详解

1 ArrayList与LinkedList对⽐(会)

相同点:
都是List集合的常⽤的实现类。
对集合中的元素操作的⽅法基本⼀致。
都是线程不安全的
​
不同点:
ArrayList底层实现是数组, 使⽤数组这种数据结构进⾏数据的存储。
LinkedList底层实现是双链表, 使⽤双链表这种数据结构进⾏数据的存储。
​
数组与链表结果特点⽐较:
数组实现功能时查找快,添加删除慢
链表查找慢,添加删除快
​
ArrayList与LinkedList的使⽤场景:
如果对集合中的元素, 增删操作不怎么频繁, 查询操作⽐较频繁。 使⽤ArrayList。
如果对集合中的元素, 增删操作⽐较频繁, 查询操作不怎么频繁。 使⽤LinkedList。

2 . 集合对⾃定义对象的存储

类分成系统类和⾃定义类
系统类往往已经重写了tostring(),equals(),hashcode()等⽅法
⾃定义类,为了实现我们的功能,往往我们需要重写⽗类的常⽤⽅法,⽐如:tostring(),equals(),hashcode()
​
示例代码:
public class Demo6 {
 public static void main(String[] args) {
 test1();
 }
 public static void test1(){
 ArrayList list1 = new ArrayList();
 list1.add("java");
 list1.add("python");
 list1.add("python");
 list1.add("iOS");
 list1.add("bigdata");
 System.out.println(list1);
 //创建临时集合
 ArrayList list2 = new ArrayList();
 Iterator i = list1.iterator();
 while (i.hasNext()){
 Object o = i.next();
 if (!(o instanceof String)){
 throw new ClassCastException();
 }
 //向下转型
 String s = (String)o;
 if (!list2.contains(s)){
 //当list1中不包换object时,将它添加进来
 /*
 * 如果判断成⽴,说明list1中不包含当前的元素
 * ⼯作原理:当添加元素时,会让当前的元素与集合中已有的元
素通过equels⽅法进⾏⼀⼀⽐较.过程中
 * 只要有⼀次返回true,停⽌⽐较.让整个的contains⽅法返回true.只有所有的⽐较都返回false,最终
* 才会返回false
 *
 * 实例:添加第三个元素的时候,调⽤equals⽅法的过程
 * 第三元素.equals("java") = false 第三元
素.equals("python") = true 停⽌⽐较
 */
 list2.add(s);
 }
  }
 System.out.println(list2);
 }

二 泛型

1 . 泛型在类中的使⽤(会)

语法部分
定义: 在类名的后⾯, 紧跟上⼀对尖括号
​
class Animal <T> {}
class Dog <T, M> {}
​
泛型类的使⽤: 声明引⽤、实例化对象、被继承。
​
// 1. 声明引⽤
Animal<String> animal;
// 2. 实例化对象
Animal<Integer> animal = new Animal<>();
// 3. 被继承
class Dog extends Animal<String> {}
class Dog<T> extends Animal<T> {}

2 . 泛型类的特点

在类中定义的泛型, 虽然还不明确是什么类型, 但是在当前类中是可以使⽤的。
在使⽤到这个类的时候, 必须要指定泛型的类型。 如果不指定, 默认是Object。
泛型, 只能在当前的类中使⽤, 不能在其他的类中使⽤, 包括⼦类。
​
示例代码L:
public class Test {
 public static void main(String[] args) {
 // 实例化⼀个对象
 // 指定了泛型的类型是 String 类型
 Person<String> xiaoming = new Person<>();
 // 泛型,是在编译前期进⾏的类型检查。⼀旦编译完成,泛型就不存在
了。
 xiaoming.part = "xiaoming";
 Person<Integer> xiaohong = new Person<>();
 xiaohong.part = 2;
 // 实例化⼀个⼦类对象
 Student student = new Student();
 student.part = "abc";
 // 实例化⼀个泛型⼦类对象
 Teacher<Integer> xiaowang = new Teacher<>();
 xiaowang.part = 132;
 // 如果多个泛型,使⽤这个类的时候,逐个进⾏类型指派即可
 Animal<String, Integer> animal = new Animal<>();
 // 如果对于⼀个泛型类,在使⽤的时候,没有指派类型,默认是 Object
类型
 Person xiaobai = new Person();
 }
}
class Animal<T, M> { }
​
class Person<T> {
 String name;
 int age;
 //在类上确定的泛型可以直接在类的内部使⽤
 T part; // 虽然现在还不明确T是什么类型,但是我们可以使⽤这个类
型。
}
class Student extends Person<T> {}
class Teacher<T> extends Person<T> { }

3 .⼦类使⽤接⼝泛型

这⾥有两种情况:
第⼀种:⼦类与接⼝泛型⼀致,接⼝可以直接使⽤泛型类型
第⼆种:接⼝使⽤泛型,⼦类不⽤,在实现的接⼝位置必须指定⼀个具体的数据类型
​
示例代码:
public class Demo9 {
 public static void main(String[] args) {
 Bird<String> bird = new Bird();
 bird.show("haha");
    }
}
interface Inter<E>{
 public void show(E e);
}
//1.⼦类与接⼝⼀致
/* 类上的泛型确定了,接⼝上的泛型就确定了,⽅法上的泛型就确定了
*/
class Bird<E> implements Inter<E>{
 @Override
 public void show(E e) {
    }
}
//2.接⼝使⽤泛型,⼦类不⽤
/*在实现的接⼝位置必须指定⼀个具体的泛型
*
* ⽅法使⽤泛型的情况:
* 1.如果是重写的⽅法,泛型与接⼝⼀致
* 2.如果是⼦类⾃⼰的⽅法,可以与接⼝⼀致,也可以有⾃⼰的泛型
*/
class Cat implements Inter<String>{
    @Override
 public void show(String s) {
    }
}
class Pig implements Comparable<Pig>{
 @Override
 public int compareTo(Pig o) {
 return 0;
    }
}
class ComWithA implements Comparator<String>{
 @Override
 public int compare(String o1, String o2) {
 ArrayList list = null;
 return 0;
    }
}

4 . 泛型在⽅法中的使⽤(会)

语法部分
定义: 泛型⽅法中, 在定义⽅法时,在返回值前⾯通过定义泛型。
​
public static <T> void test(T t) {
 
}
​
在定义处的<>⽤来定义泛型
在调⽤处的<>⽤来使⽤泛型

5 泛型⽅法的分类

第⼀:⽅法上的泛型与类上的⼀致
第⼆:⽅法上独⽴使⽤泛型
在⽅法中定义的泛型, 虽然还不明确是什么类型, 但是在当前⽅法中是可以使⽤的。
泛型⽅法, 在使⽤的时候, 不能跟类、接⼝似的, ⼿动的设置类型。 泛型⽅法中, 泛型的设置, 在参数中体现。
泛型⽅法, ⼀定需要是有参的。 参数列表中, 必须有泛型类型。
泛型⽅法中的泛型的设置, 是通过在调⽤⽅法的时候, 实参的类型推导出来的。
泛型, 只能在当前的⽅法中使⽤, 不能在其他的⽅法中使⽤。

三 Collections⼯具类(会)

示例代码:
public class CollectionsUsage {
 public static void main(String[] args) {
 // 1. 实例化⼀个List集合对象
 List<Integer> list = new ArrayList<>();
 // 2. 添加元素
 Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
 // 3. 获取⼀个集合中的最⼤值,⼤⼩⽐较通过元素对应的类实现的
Comparable接⼝进⾏⽐较
 Integer max = Collections.max(list);
 // 获取⼀个集合中的最⼤值,⼤⼩⽐较通过第⼆个参数 Comparator
 Integer max2 = Collections.max(list, (i1, i2) -> i2 -
i1);
 // 4. 获取⼀个集合中的最⼩值,⼤⼩⽐较通过元素对应的类实现的
Comparable接⼝进⾏⽐较
 Integer min = Collections.min(list);
 // 获取⼀个集合中的最⼩值,⼤⼩⽐较通过第⼆个参数 Comparator
 Integer min2 = Collections.min(list, (i1, i2) -> i2 -
i1);
 // 5. 将List集合中的数据进⾏随机的排列(洗牌)
 Collections.shuffle(list);
 // 6. 交换⼀个List集合中两个下标对应的元素
 Collections.swap(list, 0, 2);
 // 7. 将⼀个List集合中的元素倒序排列
 Collections.reverse(list);
 // 8. 将⼀个List集合进⾏排序,元素的⼤⼩⽐较规则使⽤元素对应的类
实现的Comparable接⼝进⾏⽐较⼤⼩
 Collections.sort(list);
 // 将⼀个List集合按照指定的规则进⾏升序排序,基本不⽤,List集
合中本身就有这样的排序⽅法
 Collections.sort(list, (i1, i2) -> i2 - i1);
 // 9. 集合中的元素拷⻉,将作为第⼆个参数的集合中的数据拷⻉到第⼀个
集合中
 List<Integer> copy = new ArrayList<>();
 Collections.addAll(copy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 Collections.copy(copy, list);
 // 10. 使⽤指定的数据,填充⼀个集合
 Collections.fill(list, 0);
 // 11. 将线程不安全的集合,转成线程安全的集合
 // Collections.synchronizedCollection()
 // Collections.synchronizedList()
 // Collections.synchronizedSet()
 // Collections.synchronizedMap()
 }
}

四 Set集合

1 Set集合的概念

Set集合中,没有下标的概念。
​
Set集合,是⼀个去重复的集合。 在Set集合中不会添加重复的元素的!在向⼀个Set集合中添加元素的时候, 会先判断这个元素是否已经存在了。如果存在, 则不再添加。
​
Set集合中, 数据的存储是⽆序的。
⽆序: 所谓的⽆序, 其实指的是元素的添加顺序和存储顺序是不⼀致的。
⽆序, 并不意味着随机!
​
Set接⼝, 是继承⾃Collection接⼝的。 Set接⼝中的⽅法, 都是从Collection接⼝中继承下来的, 并没有添加新的⽅法。

2 HashSet与TreeSet的区别

HashSet:底层是哈希表,线程不安全的
TreeSet:底层是⼆叉树,线程不安全的

3 HashSet & LinkedHashSet

去重原理:
解释:是通过调⽤元素的hashCode和equals⽅法实现去重,⾸先调⽤hashCode⽅法,拿到当前对象的哈希码值,去让两个对象的哈希码值进⾏⽐较,如果不同,直接认为是两个对象,不再去调⽤equals,如果相同,再继续调⽤equals⽅法,返回true认为是⼀个对象,返回false认为是两个对象
​
public class Demo3 {
 public static void main(String[] args) {
 HashSet<String> set = new HashSet<>();
 //说明Set本身的add⽅法内部实现的去重功能,默认调⽤的是元素的
hashCode和equals⽅法
 //String类已经默认重写了hashCode和equals⽅法
 set.add("java");
 set.add("php");
 set.add("bigdata");
 set.add("html");
 set.add("java");
 System.out.println(set);
 //⾃⼰制定的⽐较规则:并按照年龄和姓名⽐较,相同则认为是同⼀个⼈
 HashSet<Person> set1 = new HashSet<>();
 set1.add(new Person("bing",20));
 set1.add(new Person("bing1",210));
 set1.add(new Person("chenbing",120));
 set1.add(new Person("wangbing",207));
 set1.add(new Person("bing",20));
 System.out.println(set1);
 }
}
class Person{
 String name;
 int age;
 public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }
 @Override
 public String toString() {
 return "Person{" +
 "name='" + name + '\'' +
 ", age=" + 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 name.hashCode()+age*1000;
 }
}

4 TreeSet(会)

TreeSet是⼀个Set接⼝的实现类,底层实现是⼆叉树。这样的集合,会对添加进集合的元素进⾏去重的处理。 同时, 这个集合会对添加进⼊的元素进⾏⾃动的升序排序。
​
Comparable接⼝(默认排序)
如果某⼀个类实现这个接⼝, 表示⾃⼰实现了⼀个可以和⾃⼰的对象进⾏⼤⼩⽐较的规则。 此时, 这个类的对象就可以直接存储进TreeSet集合中了。 因为此时TreeSet集合已经知道了怎么对两个这个类的对象进⾏⼤⼩⽐较。
​
示例代码:
public class Demo8 {
 public static void main(String[] args) {
 //将字符串存⼊TreeSet
 /*
 * TreeSet的add⽅法实现的排序,去重.通过调⽤元素的compareTo⽅法
 * String类已经实现了Comparable接⼝,并重写了compareTo⽅法
 */
 TreeSet<String> set1 = new TreeSet<>();
 set1.add("java");
 set1.add("php");
 set1.add("php");
 set1.add("python");
 System.out.println(set1);
 //将Person2对象存⼊TreeSet
 //要求:⼈的年龄和姓名⽐较,年龄和姓名相同是⼀个⼈
 TreeSet<Person2> set2 = new TreeSet<>();
 set2.add(new Person2("bing",203));
 set2.add(new Person2("bing1",22));
 set2.add(new Person2("bing2",24));
 set2.add(new Person2("bing",20));
 System.out.println(set2);
 }
}
class Person2 implements Comparable<Person2>{
 String name;
 int age;
 public Person2(String name, int age) {
 this.name = name;
 this.age = age;
 }
 @Override
 public String toString() {
 return "Person2{" +
 "name='" + name + '\'' +
 ", age=" + age +
 '}';
 //⾃⼰制定⽐较规则:⼈的年龄和姓名⽐较,年龄和姓名相同是⼀个⼈
 /* @param o 和this进⾏⽐较的Person对象
 * @return ⽐较结果
 * > 0 : this > o
 * ==0 : this == o
 * < 0 : this < o
 */
 @Override
 public int compareTo(Person2 o) {
 //先⽐较年龄
 int v = this.age-o.age;
 //再⽐较姓名
 return v == 0 ? this.name.compareTo(o.name) : v;
 }
}

5 Comparator接⼝(⼈⼯排序)

定义:使⽤实现了Comparator接⼝的compare()⽅法的⽐较器对象进⾏⽐较
​
分析1:有了Comparable,为什么还要有comparator?
原因:
对于⾃定义的类,代码是我们⾃⼰编写的,所有在排序时不管是通过Comparator还
是Comparable,排序规则我们都可以⾃⼰制定,所以最终使⽤那种⽅法没有太⼤的区别
对于系统类,影响⾮常⼤.系统类中的代码我们只能⽤,不能改.这也就意味着系统类内部通过Comparable实现的⽐较规则已经确定了.这时我们想使⽤其他的规则对当前的系统类对象进⾏⽐较,只能使⽤Comparator⾃⼰重新制定⽐较规则
​
分析2:⼈⼯排序和默认排序那个优先级⾼?
答:⼈⼯排序的优先级⾼于默认排序.
我们可以让TreeSet同时获取到Comparator和Comparable的⽐较⽅法,此时对于系统类来说默认排序是系统⾃带的,通过Comparator实现的⼈⼯排序规则是我们想要的,所以系统必须让⼈⼯排序优先于默认排序,才能正常的使⽤后加的排序规则.
​
​
示例代码
//1.⽣成⼀个⽐较器(实现了Comparator接⼝的类的对象)
class ComWithLength implements Comparator<String>{
 @Override
 public int compare(String s1, String s2) {
 int num = s1.length()-s2.length();
 return num==0?s1.compareTo(s2):num;
 }
}
public class Demo5 {
 public static void main(String[] args) {
 //2.将⽐较器作⽤域TreeSet
 ComWithLength comWithLength = new ComWithLength();
 TreeSet<String> set = new TreeSet(comWithLength);
 /*
 * TreeSet的add⽅法实现的排序,去重.通过调⽤元素的compareTo⽅法
 * String类已经实现了Comparable接⼝,并重写了compareTo⽅法
 */
 set.add("java");
 set.add("php");
 set.add("bigdata");
 set.add("html");
 set.add("java");
 }
}

五 Map集合

Map是双列集合的顶级接⼝, 这个接⼝并没有继承⾃Collection接⼝。
在Map中, 更多强调的是⼀层映射关系。 在Map中存储的数据, 是⼀个个的键值对(Key-Value-Pair), 键和值是⼀⼀对应的。
需要注意:
由于Map集合并没有实现Iterable接⼝, 因此这个集合是不能使⽤增强for循环遍历的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值