线性表、栈、队列、优先队列、集合、映射表

116 阅读8分钟
java的两种类型的容器:
  • 合集(collection)
  • 映射表(map)
List的两种具体类:
A. ArrayList:用数组存储,数组动态创建。容量会自动变大,但不会自动减小
B.LinkedList:链表存储<br>

 注:
1.如果通过下标来随机访问元素,且不会在线性表的起始位置插入或删除元素,使用ArrayList效率更高
2.Array(数组)和ArrayList的区别:
    a.Array是数组,一旦创建大小是固定的,ArrayList的大小是动态可变的
    b.ArrayList实现了更多的方法和特性
    c.Array可以存储基本类型和对象类型,ArrayList只能存储对象类型
Comparable和Comparator
相同点:<br>
    1.两者都用作对象之间的比较,都可以自定义比较规则;
    2.两者都是返回一个描述对象关系的int类型整数;
不同点:
    1.实现了Comparable标识可以用自己与另一个对象进行比较;而实现了Comparator表示我可以比较其他的两个对象;
    2.使用Comparable需要修改原来的实体类,属于自然排序。而Comparator不用修改
    3.修改了Comparable实体类,Comparable也仅有一种比较规则。而Comparator可以实现多个比较规则

Comparable:内比较器,是一个接口。实现该接口需要实现接口中的comparaTo(Object o)方法,主要是当前对象与对象o比较

Comparator:外比较器,是一个接口。实现该接口需要实现接口中的compare方法。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;

class Person {
    public String name;
    public   int age;

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

    @Override
    public String toString() {
        return name+" "+age;
    }
}
public class TestComparator {
    public static void main(String[] args) {
        Collection<Person> collection=new ArrayList<>();
        collection.add(new Person("zhang",21));
        collection.add(new Person("liu",23));
        collection.add(new Person("song",22));

        collection.add(new Person("bong",22));
        collection.add(new Person("rong",22));
        collection.add(new Person("uong",22));
        
        ((ArrayList<Person>) collection).sort(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                if(o1.age<o2.age)
                    return -1;
                else if (o1.age>o2.age)
                    return 1;
                else{
                    if(o1.name.compareTo(o2.name)<0){
                        return -1;
                    }
                    else if (o1.name.compareTo(o2.name)>0)
                        return 1;
                    else{
                        return 0;
                    }
                }
            }
        });
        for (Person p:collection) {
            System.out.println(p.toString());
        }
    }
}
向量类和栈类

Stack类:pop();push(a);peek();

class Student{
    String name;
    public  Student(String n){
        name=n;
    }

    @Override
    public String toString() {
        return name;
    }
}
public class TestStack {
    public static void main(String[] args) {
        Stack< Student > students=new Stack<>();
        students.push(new Student("S"));
        students.push(new Student("C"));
        students.push(new Student("B"));
        students.push(new Student("h"));
        students.push(new Student("y"));
        students.push(new Student("j"));
        System.out.println("after push:");
        for (Student s:students
             ) {
            System.out.println(s.toString());
        }
        Student student=students.pop();
        System.out.println("pop->"+student.name);
        System.out.println("after pop:");
        for (Student s:students
                ) {
            System.out.println(s.toString());
        }
        Student ss=students.peek();
        System.out.println("after peek:");
         for(Student st:students
                ) {
            System.out.println(st.toString());
        }
    }
}
队列和优先队列

Queue接口:不能世界实例化Queue接口,可使用LinkedList替代。LinkedList实现了Dueue接口,Dueue接口实现了queue接口。 PriortyQueue类:优先队列。默认用Comparable以元素的自然顺序进行排序。拥有最小值的元素具有最高优先级,使用时最先从队列中删除,e若元素值相同则随机删除。

import java.util.PriorityQueue;
class Person implements Comparable<Person>{
    public String name;
    public   int age;

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

    @Override
    public String toString() {
        return name+" "+age;
    }

    @Override
    public int compareTo(Person o) {//自定义排序规则
        if (age< o.age)
            return -1;
        else if (age==o.age)
            return 0;
        else{
            if(name.compareTo(o.name)<0)
                return -1;
            else if (name.compareTo(o.name)==0)
                return 0;
            else{
                return  1;
            }
        }
    }
}
public class PriorityQueueDemo {
    public static void main(String[] args) {
        PriorityQueue<Person> priorityQueue=new PriorityQueue<>();
        priorityQueue.offer(new Person("A",12));//offer操作将特定元素插入优先级队列,顺序方式参照元素实现的Comparable的compareTo方法。
        priorityQueue.offer(new Person("B",11));
        priorityQueue.offer(new Person("C",15));
        System.out.println("output after some offer operations:");
        for (Person p:priorityQueue
             ) {
            System.out.println(p.toString());
        }
    }

}


输出:

output after some offer operations:
B 11
A 12
C 15

Set/Map

set接口拓展了Collection接口,规定其中不能包含重复元素:在集合中,不存在有元素e1,e2满足e1.equals(e2)返回值为true;
set的三个具体类:1.散列类HashSet
                2.链式散列集LinkedHashSet
                3.树形集TreeSet

hashSet

a.默认,初始容量为16,负载系数为0.75(0-1.0)
b.在增加集合的容量时,当元素个数超过了容量和负载系数的乘积,容量自动翻倍
c.HashSet可以用来存储互不相同的任何元素,若重复添加相同元素,则只添加第一次
d.hashCode方法:
    1.若两个对象相等则散列值必须相等
    2.两个不相等的对象可能有相同的哈希值
package hashSetDemo;

import java.util.HashSet;

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<String> set =new HashSet<>();
        set.add("beijing");
        set.add("shanghai");
        set.add("london");
        set.add("shanghai");//重复加入shanghai
        set.add("newyork");
        set.add("paris");

        System.out.println(set);
        for (String s :
                set) {
            System.out.print(s.toUpperCase()+" ");
        }
    }
}

output(自动去除了重复元素):

[london, newyork, paris, shanghai, beijing]
LONDON NEWYORK PARIS SHANGHAI BEIJING 

LinkedHashSet

1.用链表实现来扩展HashSet
2.和HashSet的主要区别:HashSet中的元素没有排序,而LinkedHashSet可以按照插入的顺序排序
3.也不允许出现重复元素

eg.

package linkedHashSetDemo;

import java.sql.SQLOutput;
import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHshSetMap {
    public static void main(String[] args) {
        Set<String> set=new LinkedHashSet<>();
        set.add("A");
        set.add("A");
        set.add("B");
        set.add("C");
        set.add("D");
        set.add("E");
        set.add("F");
        set.add("G");
        set.add("H");
        set.add("I");

        System.out.println(set);
    }
}

输出:

[A, B, C, D, E, F, G, H, I]

TreeSet

1.Set的一个子接口,确保集合中的元素是有序的
2.方法:
    last()
    first()
    headSet(Element toElement):集合中小于toElement的元素集合(返回值为SortedSet类型)
    tailSet(Element fromElement):返回集合中大于等于fromElement的元素集合(返回值为SortedSet类型)
      注:TreeSet是SortedSet的实现类
3.如果使用无参构造方法创建了一个TreeSet对象,则会假定元素类实现了Comparable接口,要使用Comparator接口,则必须使用构造方法:new TreeSet(Comparator com)
    *自定义排序方式的两种方式
    eg1.
        class Person implements Comparable{//元素类实现了Comparable接口
            @override
            public int compareTo(Person o){
                ...
                return ;
            }
        }
        public class Demo{
            public static void main(String[] args) {
                TreeSet<Person> treeSet=new TreeSet<>();
                ...
            }
        }
    eg2.
        public class Demo{
            public static void main(String[] args) {
                 TreeSet<Person> treeSet2=new TreeSet<>(new Comparator<String>(){
                    @Override
                    public int compare(String o1, String o2) {
                       return 0;
                     }
                });
                ...
            }
        }
package hashSetDemo;

import java.util.HashSet;
import java.util.TreeSet;

public class Demo {
    public static void main(String[] args) {
        HashSet<String> hashSet=new HashSet<>();
        hashSet.add("A");
        hashSet.add("A");
        hashSet.add("E");
        hashSet.add("F");
       // hashSet.add("B");
        hashSet.add("C");
        hashSet.add("D");
        System.out.println("HashSet:"+hashSet);
        TreeSet<String> treeSet=new TreeSet<>(hashSet);
        System.out.println("TreeSet:"+treeSet);
        System.out.println("TreeSet->first():"+treeSet.first());
        System.out.println("TreeSet->last():"+treeSet.last());
        System.out.println("TreeSet->headSet()"+treeSet.headSet("G"));
        System.out.println("TreeSet->tailSet()"+treeSet.tailSet("B"));
        TreeSet<String> treeSet1=new TreeSet<>();
        treeSet1.add("A");
        treeSet1.add("A");
        treeSet1.add("B");
        treeSet1.add("C");
        treeSet1.add("D");
        treeSet1.add("E");
        treeSet1.add("F");
        //返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。
        System.out.println("TreeSet->ceiling()"+treeSet1.ceiling("B"));
    }
}

output:

HashSet:[A, C, D, E, F]
TreeSet:[A, C, D, E, F]
TreeSet->first():A
TreeSet->last():F
TreeSet->headSet():[A, C, D, E, F]
TreeSet->tailSet():[C, D, E, F]
TreeSet->ceiling():B

映射表map

1.一种依照键/值对存储元素的容器
2.键可以是任意类型的对象
3.一个键和他对应的值作为一个条目被保存在映射表中
4.分为三类:HashMap、LinkedHashMap、TreeMap
5.如果需要更新映射表时不需要改变映射表中的顺序,就是用HashMap;如果需要按元素的插入顺序或访问顺序,则使用LinkedHashMap;如果需要使用映射表按照键排序,就是用TreeMap
LinkedHashMap
1.使用链表拓展实现了HashMap类
2.支持插入排序(插入map的顺序)和访问顺序排序(按最后一次被访问的顺序)
TreeMap
1.在遍历排好顺序的键时很高效
2.键可以使用Comparator接口或Comparable接口进行自定义排序
package hashSetDemo;

import java.util.*;

public class Demo{
    public static void main(String[] args) {
        HashMap<String,Integer> hashMap=new HashMap<>();
        hashMap.put("A",10);
        hashMap.put("B",11);
        hashMap.put("C",23);
        hashMap.put("E",11);
        hashMap.put("G",23);
        hashMap.put("P",11);
        hashMap.put("R",23);
        System.out.println("hashMap:"+hashMap);
        TreeMap treeMap=new TreeMap<>(hashMap);
        System.out.println("TreeMap:"+treeMap);

    }

}

output:

    hashMap:{P=11, A=10, B=11, R=23, C=23, E=11, G=23}
    TreeMap:{A=10, B=11, C=23, E=11, G=23, P=11, R=23}

Map应用实例1:统计文本中单词出现的频率

import java.util.*;

public class Demo{
    public static void main(String[] args) {
        String text = "Good Moring . have a good class. Hava a good visit. have fun!";
        Map<String,Integer> map=new HashMap<>();

        //将语句分隔开存储在words数组
        String[] words=text.split("[ \n\t\r.,;:!?(){}]");
        for (int i=0;i<words.length;i++){
            String key=words[i].toLowerCase();
            if(key.length()>0){
                //map不包含该key,加入
                if (!map.containsKey(key)){
                    map.put(key,1);
                }
                else{
                    //map.get(key):获取key键值对应的value
                    int value=map.get(key);
                    value++;
                    //map.put:若该元组不存在,则加入;若存在,则更新,即如果此映射以前包含一个该键的映射关系,则用指定值替换旧值(当且仅当 m.containsKey(k) 返回 true 时,才能说映射 m 包含键 k 的映射关系)
                    map.put(key,value);
                }
            }
        }
        //如果想单独访问Map的元素,需将其转化为实体集Set,用到map.entrySet().
        Set<Map.Entry<String,Integer>> entrySet=map.entrySet();
        for (Map.Entry<String, Integer> entry:
             entrySet) {
            System.out.println(entry.getKey()+" "+entry.getValue());
        }

    }
}

output:
    a 2
    moring 1
    hava 1
    have 2
    visit 1
    good 3
    class 1
    fun 1

map应用实例2:查找字符串数组重复次数最多的字符串的重复次数

import java.util.*;
public class Demo{
    public static void main(String[] args) {
        String []text = {"Hello","Back","Demo","Demo","Demo","Good","Good","some","Double","long","Hello","Hello","Hello"};
        Map<String,Integer> map=new HashMap<>();
        for (String s :
                text) {
            Integer integer=map.get(s);
            map.put(s,integer==null?1:integer+1);
        }
        int max=-1;
        String res="";
        for (Map.Entry<String,Integer> entry:
            map.entrySet()){
            System.out.println(entry.getKey()+" "+entry.getValue());
            if(max<entry.getValue()){
                max=entry.getValue();
                res=entry.getKey();
            }
        }
        System.out.println("重复次数最多的字符串为 \""+res+"\" ,重复次数为"+max);
    }
}


output:
    some 1
    Demo 3
    Hello 4
    Back 1
    Good 2
    Double 1
    long 1
    重复次数最多的字符串为 "Hello" ,重复次数为4