Day21知识总结

知识补充

增强型for循环

增强型for循环 for(类型 变量名:集合/数组){使用变量}
集合遍历使用lambda/forEach更简化,只有引用类型才能使用

for(泛型类型 引用:集合)
{引用指向的就是集合中的每一个元素}
[其中元素类型需要一致,即是范型]

for(数组元素的类型 变量名:数组)
{变量名的值就是数组中的每一个元素}

//增强型for循环 for(类型 变量名:集合/数组){使用变量}
//集合遍历使用lambda/forEach更简化,只有应用在引用
  public static void main(String[] args) {
        List<Integer> list=new ArrayList<>();
        list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
//for(泛型类型 引用:集合){引用指向的就是集合中的每一个元素}[其中元素类型需要一致,即是范型]
        for (Integer i:list)
            System.out.println(i);
        char[] c={'A','B','D','E'};
//for(数组元素的类型 变量名:数组){变量名的值就是数组中的每一个元素}
        for(char c1:c)
            System.out.println(c1);

    }

subList() 获取子list

subList() ,获取的子list和原来的list占有相同的存储空间;

		List<Integer> list=new ArrayList<>();
        //给list赋值0-9
        for(int i=0;i<=9;i++)
            list.add(i);
        System.out.println(list);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        //截取子串subList()
        List<Integer> sublist=list.subList(4,8);
        System.out.println(sublist);//[4, 5, 6, 7]

把list中(4,8)的元素扩大10,输出list

方法一

遍历每个元素,先利用sublist.indexOf(i)找到该元素位置;
再对该元素利用set(index,元素)进行修改

for(int i:sublist)
     sublist.set(sublist.indexOf(i),i*10 );
System.out.println(list);
//[0, 1, 2, 3, 40, 50, 60, 70, 8, 9]
方法二

循环每一个下标,利用get(i)获取每个元素值,再使用set(i,元素进行修改)

for(int i=0;i<sublist.size();i++)
      sublist.set(i,sublist.get(i)*10);
System.out.println(list);
//[0, 1, 2, 3, 40, 50, 60, 70, 8, 9]

删除索引为奇数位的元素

方法一 从后往前减
for(int i=list.size()-1;i>=0;i--)
		if(i%2!=0)
			list.remove(i);
System.out.println(list);
方法二 遍历interator()
        int index=0;
        Iterator<Integer> i = list.iterator();
        while (i.hasNext()){
            i.next();
            if(index++%2!=0){
                i.remove();
            }
        }
方法三 利用subList()
for (int i=0;i<list.size();i++){
		list.subList(i+1,i+2).clear();
}
System.out.println(list);
方法四
for (int i=0;i<list.size();i++){
      if(i+1<list.size()){
      		list.remove(i+1);
      }
}
System.out.println(list);

LinkedList集合

List接口的实现类:ArrayList、LinkedList

ArrayList 动态数组实现,适合随机访问元素[线性表]
LinkedList 链表实现,适合插入与删除元素[双向链表]
ArrayList与LinkedList

不同父类能调用的方法不同

 LinkedList<Point> ps=new LinkedList<>();
//ps能调用到LinkedList中所有方法
List<Point> ps1=new ArrayList<>();
//ps1能调用到List中所有方法
Collection<Point> ps2=new LinkedList(); 
//ps2这个引用只能调用到Collection接口中定义的方法

实现List接口

add(元素) 添加元素
get(index) 根据索引,获取元素
add(index,元素) 插入元素
remove(index)、remove(元素) 根据索引或者元素,删除元素
size() 列表元素个数
iterator()、forEach() 循环遍历输出元素
clear() 清空列表元素
isEmpty() 判断列表是否为null
元素可重复,且有序列表,即按存入顺序存放元素

class Point{
    int x,y;
    public Point(int x,int y){
        this.x=x;
        this.y=y;
    }

    @Override
    public String toString() {
        return "Point{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}
public class Demo1List {
    public static void main(String[] args) {
        List<Point> ps=new ArrayList<>();
        //ps能调用到List中所有方法
        
        //add(元素)添加元素
        ps.add(new Point(1,1));
        ps.add(new Point(2,2));
        ps.add(new Point(3,3));

        //get(index)获取元素
        System.out.println(ps.get(2));//Point{x=3, y=3}
        
        //add(index,元素)插入元素
        Point p=new Point(10,10);
        ps.add(1,p);
        System.out.println(ps);
//[Point{x=1, y=1}, Point{x=10, y=10}, Point{x=2, y=2}, Point{x=3, y=3}]
        //元素可重复
        ps.add(p);
        System.out.println(ps);
//[Point{x=1, y=1}, Point{x=10, y=10}, Point{x=2, y=2}, Point{x=3, y=3}, Point{x=10, y=10}]

        //删除最后一个remove(index)、remove(元素)
        ps.remove(ps.size()-1);
        System.out.println(ps);
//[Point{x=1, y=1}, Point{x=10, y=10}, Point{x=2, y=2}, Point{x=3, y=3}]

        //修改元素set(index,元素)
        Point temp=ps.get(0);
        ps.set(0,ps.get(ps.size()-1));
        ps.set(ps.size()-1,temp);
        System.out.println(ps);
//[Point{x=3, y=3}, Point{x=10, y=10}, Point{x=2, y=2}, Point{x=1, y=1}]

        //循环遍历
        //Iterator
        Iterator<Point> i = ps.iterator();
        while (i.hasNext())
            System.out.println(i.next());
        //forEach
        ps.forEach((o)->{
            System.out.println(o);
        });
        
        //清空clear()
        ps.clear();
        System.out.println(ps);//[]
        
        //判空isEmpty()
        System.out.println(ps.isEmpty());//true
    }
}

实现Queue接口[队列]

LinkedList类实现Deque< E >接口、Deque< E >接口继承Queue< E >接口

LinkedList类实现Deque< E >接口

LinkedList类实现Deque< E >接口

Deque< E >接口继承Queue< E >接口

Deque< E >接口继承Queue< E >接口 Queue<类型> queue=new LinkedList<>();

offer(元素); 元素入队[右入]
pool(); 首元素出队[左出]
peek(); 查找出队元素

public static void main(String[] args) {
        Queue<String> queue=new LinkedList<>();

        //元素入队 offer(元素)
        queue.offer("A");
        queue.offer("B");
        queue.offer("C");
        queue.offer("D");
        
        //查看队列中首元素peek()
        System.out.println("队首元素"+queue.peek());//左出 //队首元素A
        
        //循环出队 元素出队poll()
        while (queue.peek()!=null)
            System.out.println(queue.poll());//出队
        //若队列中没有元素即队首为null],若继续出队,则返回为null[
        System.out.println(queue.poll());//null
    }

当队列中没有元素即队首为null ,若继续出队,则返回为null

//循环出队 元素出队poll()
while (queue.peek()!=null)
     System.out.println(queue.poll());//出队
     //若队列中没有元素即队首为null],若继续出队,则返回为null[
System.out.println(queue.poll());//null

实现Deque接口 [栈]

Deque<类型> statck=new LinkedList<>();

push(元素) 入栈
pop() 出栈
peek() 寻找出栈元素

 public static void main(String[] args) {
        Deque<String> statck=new LinkedList<>();
        //入栈
        statck.push("A");
        statck.push("B");
        statck.push("C");
        statck.push("D");
        //寻找栈最先的出栈元素 peek()
        System.out.println(statck.peek()); //D
        while (statck.peek()!=null)
            System.out.print(statck.pop()+" ");//出栈顺序 D C B A
        //System.out.println(statck.pop());
        //空栈继续出栈[即当出栈元素为null时] java.util.NoSuchElementException
    }

当空栈继续出栈[即当出栈元素为null时] ,运行错误

java.util.NoSuchElementException

Comparable< T > 接口

Comparable 是接口,comparaTo(o) 比较大小方法
两个对象比大小,返回类型为int

int i=元素1.comparaTo(元素2)
i>0表示元素1大;
i<0表示元素2大;
i==0,两个元素相等

String类型实现Comparable< String >接口,重写了comparaTo(o) 方法,默认比较对象的字母大小

String s="tome";
String s1="Tome";
//int i=元素1.comparaTo(元素2) 比较大小
//i>0表示元素1大;i<0表示元素2大;i==0,两个元素相等
int i=s.compareTo(s1);//i=32

Collections.sort(list);

Collections 一个工具包,如同Arrays
新建五个Student对象,放入List表中进行排序

public static void main(String[] args) {
        Student tom = new Student("tom", 19);
        Student jack = new Student("jack", 20);
        int a=tom.compareTo(jack);
        System.out.println(a>0?"tom大":a<0?"jack大":"一样大");//jack大

        List<Student> stu=new ArrayList<>();
        stu.add(new Student("1",12));
        stu.add(new Student("2",18));
        stu.add(new Student("3",13));
        stu.add(new Student("4",14));
        stu.add(new Student("5",11));
        System.out.println(stu);
        
//[Student{name='1', age=12}, Student{name='2', age=18}, Student{name='3', age=13}, Student{name='4', age=14}, Student{name='5', age=11}]

        //方法一

//        stu.sort(((o1, o2) ->{
//            return o1.compareTo(o2);//本质调用类型中的compareTo()方法
//        }));
//        System.out.println(stu);//调用类型本身的toString()

//[Student{name='5', age=11}, Student{name='1', age=12}, Student{name='3', age=13}, Student{name='4', age=14}, Student{name='2', age=18}]

        //方法二
        //方法一等价于方法二
        Collections.sort(stu);//默认升序
        //Student实现了Comparable接口,重写了comparTo()方法
        System.out.println("排序后"+stu);
        
//排序后[Student{name='5', age=11}, Student{name='1', age=12}, Student{name='3', age=13}, Student{name='4', age=14}, Student{name='2', age=18}]



    }
//public interface Comparable<T>{} 范化接口
class Student implements Comparable<Student>{
    String name;
    int age;
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }
    @Override
    public int compareTo(Student o) { //Student实现了Comparable接口,重写了comparTo()方法
        return this.age-o.age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Comparator < T >接口

对已经重写过重写过comparaTo(o) 方法的类,对comparaTo(o) 方法进行规则重写,自定义比较规则

@FunctionalInterface
  public interface Comparator<T> {int compare(T o1, T o2);}

Collections.sort(集合,Comparator[重写规则])

String类型实现Comparable< String >接口,重写了comparaTo(o) 方法,默认比较对象的字母大小

按字符串长度排序 使用Collections.sort(集合,Comparator[重写规则])
默认规则:Collections.sort(集合)

List<String> str=new ArrayList<>();
str.add("hello");str.add("tom");str.add("nice to meet you");str.add("hi");str.add("hanmeimei");
 //[hello, tom, nice to meet you, hi, hanmeimei]

Collections.sort(str); //默认按字符大小排序
System.out.println(str);
//[hanmeimei, hello, hi, nice to meet you, tom]

重写规则:Collections.sort(集合,Comparator[重写规则])
自定义排序规则,重写排序规则

        //匿名内部类
        Collections.sort(str, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length()-o2.length();
            }
        });
        //lambda函数 函数式接口
        Collections.sort(str,(o1,o2)->{
            return o1.length()-o2.length();
        });
        System.out.println(str);
 //[hi, tom, hello, hanmeimei, nice to meet you]

Set集合

Set不重复的、无序的

Set集合中的元素,不能和顺序的下标对应,无法从Set集合中获取除特定的元素

Set存储不重复的对象集合,set集合中存储的对象
不存在两个对象的引用地址相等;
对象是否重复取决于equals()方法是否重写

Set继承了Collection
HashSet 用hash表实现了Set集合
TreeSet 用排序二叉树实现了Set集合

add(元素) 添加元素 在集合中没有顺序,不支持排序
size() 获取元素个数
remove(元素) 删除指定元素
clear() 清空元素
isEmpty() 判断集合是否为空

遍历
1,增强版for(类型 变量:集合)
2,forEach(x->System.out.println(x))
简写 forEach(System.out::println)

Set集合无序

Set无序:add(元素)添加的元素在集合中没有顺序,不支持排序

		Set<String> set=new HashSet<>();
        //Set无序:添加的元素在集合中没有顺序,不支持排序
        set.add("A");
        set.add("C");
        set.add("D");
        set.add("B");
        System.out.println(set);//[A, B, C, D]

Set集合不重复

		set.add("C");
        set.add("D");
        set.add("B");
        System.out.println(set);//[A, B, C, D]
		//其他方法
        System.out.println(set.size());
        System.out.println(set.remove("A"));
        //set.clear();
        //System.out.println(set.isEmpty());

Set集合遍历

for(类型 变量:集合)

for(String s:set)
            System.out.println(s);

forEach(x->System.out.println(x))
简写 forEach(System.out::println)

 //forEach
 //一个参数,可省略小括号
//set.forEach(x-> System.out.println(x));
set.forEach(System.out::println);//简写

在集合中存储20个不重复的100以内的整数

Set<Integer> sets=new HashSet<>();
        Random random=new Random();
        while (sets.size()<20){
            sets.add(random.nextInt(100)+1);
        }
        System.out.println(sets);

给数组去重

//给数组元素去重
        int[] arr={1,2,32,3,43,2,1};
        Set<Integer> sets2=new HashSet<>();
        for (int i:arr)
            sets2.add(i);
        System.out.println(sets2);

Map集合

Map集合,存储"key-value"键值对;
key为value的索引、通过key查找value;
key不能重复;但key值是否重复,取决于equals();
key值可以是null,但只允许有一个key为null
无序

Map是一个接口,实现类HashMap、ThreeMap
常用get、put
依据key找value

put(key,value) 增加数据
当key值已存在,put(key,value) 则修改该key索引的vaule值
size() 元素个数

containsKey(key) 是否包含某个key值,返回类型boolean类型
containsValue(value) 是否包含某个value值,返回类型boolean类型

get(key) 通过key找value 返回value类型的value值,否则返回value类型的默认值[引用类型:null]
remove(key)根据key删除对应元素集合,返回被删除的value类型的value值,否则返回value类型的默认值[引用类型:null]

keySet() 取出集合中所有的keys值,返回类型为Set集合
values() 取出所有的values值,返回类型为Collection集合

clear() 清空元素
isEmpty()判空

常用方法

put(key,value) 增加 / 修改数据、size()

put(key,value) 增加数据

Map<String,Integer> map=new HashMap<>();
//增加数据 put(key,value)
map.put("语文",80);
map.put("数学",70);
map.put("英语",60);
 System.out.println(map);
//{数学=70, 语文=80, 英语=60} //Map 无序

put(已存在key,value) 修改value值;

//修改value值 key已存在时,put(已存在key,value) 修改value值
map.put("语文",90);
System.out.println(map);
//{数学=70, 语文=90, 英语=60}
//元素个数 size()
System.out.println(map.size());//3

containsKey(k)、containValue(v)是否包含

//是否包含某个key值 containsKey(key)
System.out.println(map.containsKey("语文"));//true

//是否包含某个value值 containsValue(value)
System.out.println(map.containsValue(70));//true

get(key)、remove(key)

//get(key) 通过key找value,返回value值;若不存在,返回null
System.out.println(map.get("语文"));//90
System.out.println(map.get("物理"));//null

//根据key删除集合中的元素 返回删除元素的value值;若不存在,返回null
System.out.println(map.remove("语文"));//90
System.out.println(map.remove("物理"));//null

keySet()、values()

//key的Set集合
//key的Set集合,取出所有的keys值
Set<String> keys=map.keySet();
System.out.println(keys);//[数学, 英语]

//value的Collection集合,取出所有的values值
Collection<Integer> values=map.values();
System.out.println(values);//[70, 60]

clear()、isEmpty()

map.clear();
System.out.println(map.isEmpty());//true

key值是否重复,取决于equals

key值是否重复,取决于equals()方法是否被重写;
若未重写,则比较两个对象是否是同一个对象;
若重写,则比较两个对象的属性是否相同
key值可以是null,但只允许有一个key为null

class Person{
    String id;
    String name;
    int age;

    public Person(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public static void main(String[] args) {
        //id 找到Person
        Map<String,Person> map=new HashMap<>();
        map.put("101",new Person("101","小红",20));

        Person person=map.get("101");
        person.age=23;
        //等价于map.get("101").age=23;
        //"101"编号的Person属性age改变
        System.out.println(map.get("101"));//Person{id='101', name='小红', age=23}

        //通过人找人
        //key不能重复,可以是null,但允许有一个key是null 是否重复取决于equals()方法是否重写
        Map<Person,Person> map1=new HashMap<>();
        map1.put(new Person("101","小红",20),new Person("101","小红",20)); 
        map1.put(new Person("101","小红",20),new Person("101","小红",20));
//虽然属性均一样,但是存放在不同的地址中,且Student类没有重写equasl()方法
        map1.put(null,new Person("101","小红",20));
        map1.put(null,new Person("101","小红",20));
        System.out.println(map1.size());//3
  }

遍历

//map遍历
        Map<String,Integer> map2=new HashMap<>();
        map2.put("语文",80);
        map2.put("数学",70);
        map2.put("英语",60);
        map2.put("物理",70);
        map2.put("化学",70);

entrySet()

entrySet()遍历-> 将(key,value)作为一行,存储

Set<Map.Entry<String, Integer>> entries = map2.entrySet();
        //方法一:entrySet()遍历->将(key,value)作为一行,存储
        for(Map.Entry<String,Integer> entry:entries)
            //entry就是一个键值对
            System.out.println(entry.getKey()+"----"+entry.getValue());

entrySet()

keySet()

先取出keys集合,再通过key索引value值

Set<String> keys=map2.keySet();
for(String key:keys)
      System.out.println(key+"++++"+map2.get(key));

keySet()

forEach()

void forEach(BiConsumer<? super K, ? super V> action)
public interface BiConsumer<T, U> { void accept(T t, U u);}

map2.forEach((k,v)->{
            System.out.println(k+"===="+v);
        });

forEach()

面试题

集合有哪些

collection接口的子类包含:Set接口与List接口
List接口的实现类:ArrayList、LinkedList、Stack、Vector等;

List接口的实现类:有序且数据可重复的集合

Set接口的实现类:HashSet、TreeSet、LinkedHashSet等

Set接口的实现类:无序且数据不重复集合

Map接口的实现类:HashMap、ThreeMap、Properties

Map接口的实现类,无序且键不重复的键值对集合

简述HashMap的实现原理

HashMap基于Hash算法实现的, 我们通过put(key, value)存储数据, get(key)取数据,当传入key的时候,HashMap会根据key.hashCode()计算hash值,根据hash值将value保存再bucket中(以数组的形式保存)。
当我们计算出的hash值相同时,我们称为hash冲突,HashMap的做法是用链表和红黑树存储相同的hash值对应的value。当hash冲突的个数比较少(阈值为8.),就使用链表, 比较多就使用红黑树

了解红黑树

红黑树,本质是一颗二叉搜索树 + 节点颜色限制(红/黑) + 规则约定(最长路径中的节点个数不超过最短路径中节点个数的2倍)
红黑树详细讲解与用法

理解java泛型

java泛型(参数化类型)
泛型是java 1.5引入的新特性,泛型的本质是参数类型化

在类,接口和方法的定义过程中,所操作的数据类型被传入的参数指定

java泛型机制广泛地应用于集合中,所有集合类型都带有泛型

在创建集合对象的时候,指定集合中元素的类型

java编译器根据泛型的类型,对集合中元素进行类型检查,减少运行的时候错误

泛型应用场景

class 类名<泛型> – 泛型代表一种类

相当于是一个参数,类定义的时候,不知道具体的类型, 使用类来创建对象的时候,在指定具体类型.

泛型类

泛型类

class MyDog<D>{
D d;
public MyDog(D d){
this.d = d;
}
}

使用泛型类

public static void main(String[] args) {
MyDog<String> m = new MyDog<>("dd");
System.out.println(m.d);
MyDog<D> k = new MyDog<D>(new Date()); 
// 编译错误 -- 作为一个类型使用的时候,泛型必须指定为某个具体存在的类型
}
泛型接口

类实现接口的时候, 需要指定具体的类型

泛型接口

interface MyCat<E>{
public E getE();
public void setE(E e);
}

实现泛型接口

class AA implements MyCat<String> {
@Override
public String getE() {
return null;
}
@Override
public void setE(String o) {
}
}
泛型方法
class BB{
// <T> -- 定义方法的发返回值前,代表方法要使用泛型
public <T> void fun1(T t){
}
public <T> T fun2(T t){
return t;
}
public <T> String fun3(T t){
return "hello";
}
}

通配符

<?> 无界通配符

不确定类型,可以是任意类型

< ? extends T > ,上边界通配符

?是继承自T的任意子类型 , 遵守只读不写(只能作为返回值类型)

< ? super T > , 下边界通配符

? 是 T的任意父类, 遵守只写不读(只能作为参数 , 作为返回值类下,始终返回Object ,意义不大.)

// <?> 无界通配符,即不确定类型,可以是任意类型
class CC<Z>{
}
// <? extends T> ,上边界通配符, 即?是继承自T的任意子类型 , 遵守只读不写(只能作为返回
值类型)
class DD<T1 extends CC>{
public void get(T1 t){
}
}
// <? super T> , 下边界通配符,即? 是 T的任意父类, 遵守只写不读(只能作为参数 , 作为返回值类下,始终返回Object ,意义不大.)
//class EE1<e super FF>{
//}
public class TPFTest {
public static void main(String[] args) {
// 限制元素是Number或者Number的子类.
List<? extends Number> list1 = new ArrayList<>();
list1.add(null);
// Number的子类有Integer , Double , 编译器没有办法确定add时的子类对象 ,所以添加不成功.
Integer i = 100;
//list1.add(i); 编译错误: ? extend T 上界类型通配符, 只读,不能写. add函数受限制.
Number number = list1.get(0); // 可以取出来使用.
// 限制元素是Intger或其父类.
List<? super Integer> list2 = new ArrayList<>();
list2.add(100);
//Integer object = list2.get(0); // 编译错误 : ? super T 下界类型通配符 ,因为没有办法确定父类是谁 , 只能写,不能读.
// 结论:又要写,又要读,写指定的泛型:
List<Integer> list = new ArrayList<>();
list.add(100);
Integer integer = list.get(0);
}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值