1 查找
1.1 二分查找
public class Main {public static void main(String[] args) throws IOException, CloneNotSupportedException, ParseException {
//数组必须有序int[] arr={1,2,4,5,6,24,123};System.out.println(binarySearch(arr,123));//6}public static int binarySearch(int[] arr,int num){int min=0;int max=arr.length-1;while (true){if(min>max){return -1;}int middle=(max+min)/2;if(arr[middle]>num){max=middle-1;}else if(arr[middle]<num){min=middle+1;}else{return middle;}}};
}
1.2 插值查找
数据要有顺序
1.3 分块查找
索引表
package DEMO1;import java.io.IOException;
import java.text.ParseException;public class Main {public static void main(String[] args) throws IOException, CloneNotSupportedException, ParseException {int[] arr={5,4,3,2,7,9,8,6,11,14,13,15};Block b1=new Block(5,0,3);Block b2=new Block(9,4,7);Block b3=new Block(15,8,11);
// 创建索引表Block[] blockarr={b1,b2,b3};
// 要查找的元素int num=9;System.out.println(getIndex(blockarr,arr,num));//5}private static int getIndex(Block[] blockarr, int[] arr, int num) {int n=NumBlock(blockarr,num);if (n == -1) {return -1;}int start=blockarr[n].getStartIndex();int end=blockarr[n].getEndIndex();for (int i = start; i < end; i++) {if (arr[i] == num) {return i;}}return -1;};//num在哪一块private static int NumBlock(Block[] blockarr, int num) {for (int i = 0; i < blockarr.length; i++) {if(num<=blockarr[i].getMax()){return i;}}return -1;};
}
class Block{private int max;private int startIndex;private int endIndex;//ptg生成public Block() {}public Block(int max, int startIndex, int endIndex) {this.max = max;this.startIndex = startIndex;this.endIndex = endIndex;}/*** 获取* @return max*/public int getMax() {return max;}/*** 设置* @param max*/public void setMax(int max) {this.max = max;}/*** 获取* @return startIndex*/public int getStartIndex() {return startIndex;}/*** 设置* @param startIndex*/public void setStartIndex(int startIndex) {this.startIndex = startIndex;}/*** 获取* @return endIndex*/public int getEndIndex() {return endIndex;}/*** 设置* @param endIndex*/public void setEndIndex(int endIndex) {this.endIndex = endIndex;}public String toString() {return "Block{max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";}
}
1.4 hash查找
2 排序
2.1 冒泡排序
int[] arr={4,5,2,1,3};for(int j=0;j<arr.length;j++){for (int i = arr.length-1; i >0; i--) {if(arr[i]<arr[i-1]){int temp=arr[i-1];arr[i-1]=arr[i];arr[i]=temp;}}}for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);//1 2 3 4 5}
2.2选择排序
2.3 插入排序
int[] arr={4,5,2,1,3};
// 1.记录无序数组第一个索引int start = -1;for (int i = 1; i < arr.length; i++) {if(arr[i-1]>arr[i]){start=i;break;}}
// 2.遍历无序数组for (int i = start; i < arr.length; i++) {int j=i;while(j>0&&arr[j-1]>arr[j]){int temp=arr[j];arr[j]=arr[j-1];arr[j-1]=temp;j--;}}for (int j : arr) {System.out.println(j);}
2.4 快速排序
int[] arr={4,5,2,1,3};long start=System.currentTimeMillis();quick(arr,0,arr.length-1);for(int i:arr){System.out.println(i);//1 2 3 4 5}long end= System.currentTimeMillis();System.out.println(end-start);//执行快速排序所花的时间}public static void quick(int arr[],int start,int end){//第一轮int i=start;int j=end;if(start>end){//递归出口return;}int basicN=arr[start];while (start!=end){while (true){if(end<=start||arr[end]<basicN)break;end--;}while (true){if(end<=start||arr[start]>basicN)break;start++;}int temp=arr[start];arr[start]=arr[end];arr[end]=temp;}int temp=arr[start];arr[start]=arr[i];arr[i]=temp;quick(arr,i,start-1);quick(arr,start+1,j);
3 集合
3.1 集合体系结构
单链集合Collection
双列集合Map
list 允许重复,set不允许重复
有序:存和取的元素顺序一致(队列)
3.2 Collection集合
3.2.1 方法
public class Frog {public static void main(String[] args) {
// Collection是一个接口,不能直接创建其对象Collection<String> co=new ArrayList<>();co.add("11");co.add("22");System.out.println(co);//[11, 22]
// 全部清空
// co.clear();System.out.println(co.remove("11"));//trueSystem.out.println(co);//[22]
// 是否包含//底层依赖equals判断,如果存储自定义对象用contains,要重写System.out.println(co.contains("22"));//trueCollection<Dog> coDog=new ArrayList<>();Dog d1=new Dog("do1",18);Dog d3=new Dog("do1",18);coDog.add(d1);coDog.add(d3);System.out.println(d1.equals(d3));//trueSystem.out.println(coDog.isEmpty());//false//集合长度System.out.println(coDog.size());//2}
}
Dog.java
public class Dog {private String name;private int age;public Dog() {}public Dog(String name, int age) {this.name = name;this.age = age;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Dog dog = (Dog) o;return age == dog.age && Objects.equals(name, dog.name);}public String toString() {return "Dog{name = " + name + ", age = " + age + "}";}
}
Dog.java需要重写equals方法:点到底就可以
3.2.2 遍历
1 迭代器遍历
不依赖索引
public class Frog {public static void main(String[] args) {
// Collection是一个接口,不能直接创建其对象Collection<String> co=new ArrayList<>();co.add("11");co.add("22");co.add("33");
// 迭代器Iterator<String> it=co.iterator();
// hasNext()判断当前元素是否有值while (it.hasNext()){//next();获取当前元素,并将迭代器对象移到下一个位置//循环中只能用一次next方法,如用多次该值给变量String s=it.next();//System.out.println(it.next());NoSuchElementException,循环只能用一次next方法System.out.println(s);
// 当上面循环结束,迭代器指针指向没有元素的位置// 迭代器遍历,不能用集合的方法删除或者添加if("33".equals(s)){// co.add("45");//ConcurrentModificationException//添加没办法,删除可以用迭代器对象删除it.remove();}}//System.out.println(it.next());//NoSuchElementException没有索引异常,只是没有元素
// 迭代器遍历完毕,指针不会复位System.out.println(it.hasNext());//false}
}
2 增强for遍历
内部是Iterator迭代器
单列集合、数组用增强for遍历
Collection<String> co=new ArrayList<>();co.add("11");co.add("22");co.add("33");
// 快捷:co.for//遍历时只是把数据交给s记录,改变s的值不会改变co的值for(String s:co){System.out.println(s);}
3 Lambda表达式遍历
Lambda表达式(匿名函数)前提:必须是函数接口匿名内部类,接口中只能有一个抽象方法
省略规则:
// Collection是一个接口,不能直接创建其对象Collection<String> co=new ArrayList<>();co.add("11");co.add("22");co.add("33");//自己遍历集合,获得每一个元素,传递给accept方法co.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});
// 简化版本co.forEach((String s)-> {System.out.println(s);});
// 更简化版本co.forEach(s->System.out.println(s));
}}
3.3 List集合
List<Integer> list=new ArrayList<>();list.add(1);list.add(2);list.add(3);System.out.println(list);//[1, 2, 3]//原来索引元素依次往后移list.add(1,4);System.out.println(list);//[1, 4, 2, 3]
// 当方法重载调用,删除元素优先删除实参与形参一致的方法//调用value==1的还是index==1?list.remove(1);System.out.println(list);//[1, 2, 3]list.add(1,4);
// 手动装箱Integer i=Integer.valueOf(1);list.remove(i);System.out.println(list);//[4, 2, 3]
// 修改Integer in=list.set(0,5);System.out.println(in);//4System.out.println(list);//[5, 2, 3]
// 获取值System.out.println(list.get(2));//3
remove两种方法,当方法重载调用,删除元素优先删除实参与形参一致的方法
遍历
public class Frog {public static void main(String[] args) {List<Integer> list=new ArrayList<>();list.add(1);list.add(2);Iterator<Integer> it=list.iterator();while (it.hasNext()){Integer it1=it.next();System.out.println(it1);//1 2}for(Integer i:list){System.out.println(i);//1 2}list.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);//1 2}});list.forEach(integer-> System.out.println(integer));//1 2for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}}
3.4 ArrayList集合
查看源码:
ctrl+n:搜索ArrayList
alt+7或者ctrl+f12:
3.4.1 空参构造
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
选中elementData:ctrl+b
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
当用空参构造创建对象,底层创建一个长度为0的数组
3.4.2 add
ArrayList<Integer> arr=new ArrayList<>();arr.add(1);
public boolean add(E e) {modCount++;
//e:当前要添加的元素
//elementData:底层数组名
//size:集合的长度/当前元素应存入的位置add(e, elementData, size);return true;}
跟进中间add方法
private void add(E e, Object[] elementData, int s) {if (s == elementData.length)
//新方法满了用无参grow方法扩容elementData = grow();elementData[s] = e;size = s + 1;}
private Object[] grow() {
//有参growreturn grow(size + 1);}
private Object[] grow(int minCapacity) {
//第一次添加, minCapacity=1,oldCapacity=0int oldCapacity = elementData.length;
//如果老容量不等于0或者数组不等于空数组if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//计算数组新长度int newCapacity = ArraysSupport.newLength(oldCapacity,
//如果10个存满要扩容,此时minCapacity - oldCapacity=11-10=1minCapacity - oldCapacity, /* minimum growth */oldCapacity >> 1 /* preferred growth */);
//copyOf进行老数组复制到新数组,elementData是老的数组,newCapacity是新的数组长度return elementData = Arrays.copyOf(elementData, newCapacity);} else {
//Math.max比较谁大,DEFAULT_CAPACITY=10.minCapacity=1return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];}}
//如果10个存满要扩容,oldLength=10,minGrowth=1,prefGrowth=5
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {// preconditions not checked because of inlining// assert oldLength >= 0// assert minGrowth > 0
//比较的原因是新增的数可能比老容量多得多,集合可以一次添加多个元素int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflowif (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {return prefLength;} else {// put code cold in a separate methodreturn hugeLength(oldLength, minGrowth);}}
3.5 LinkedList集合
底层是双链表
//内部类,表示链表结点private static class Node<E> {
//表示现在我要存储的数据E item;
//下一个节点的地址值Node<E> next;
//前一个节点的地址值Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{transient int size = 0;transient Node<E> first;transient Node<E> last;//使用空参构造,其成员变量存在,但都是默认值public LinkedList() {}
public boolean add(E e) {linkLast(e);return true;}
void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;}
4 泛型
没有给集合指定类型,那么默认都是Object类型,如多态一样不能访问子类的特有功能
泛型不能写基本数据类型,因为不是object类
4.1 泛型类
MyArrayList.java
public class MyArrayList<E> {Object[] obj=new Object[10];int size;
// E表示不确定的类型public boolean add(E e){obj[size]=e;size++;return true;}public E get(int index){return (E)obj[index]; }
//作用:打印的不是地址值,而是属性值@Overridepublic String toString() {
// 把数组所有元素都拼接为字符串再返回return Arrays.toString(obj);}
}
Frog.java
public class Frog {public static void main(String[] args) {//String传给EMyArrayList<String> list=new MyArrayList<>();list.add("111");list.add("112");String s=list.get(1);System.out.println(s);//112
}}
4.2 泛型方法
MyArrayList.java
public class MyArrayList {
// 第一个<E>表示我已经定义的不确定类型E//E...e 表示可变参数,传一个或者多个都可以,底层是数组public static <E> void addL(ArrayList<E> list, E...e){//e.for回车:快捷,增强forfor (E e1:e){list.add(e1);}}
}
Frog.java
public class Frog {public static void main(String[] args) {ArrayList<String> arr= new ArrayList<>();MyArrayList.addL(arr,"1","2","3");System.out.println(arr);//[1, 2, 3]
}}
4.3 泛型接口
//java定义的泛型接口public interface List<E> extends Collection<E> {...}//使用方式1
public class Frog implements List<String> {}//使用方式2
public class Frog<E> implements List<E> {}
4.4 泛型通配符
5 set集合
方法基本与Collection的API一致
5.1 HashSet
无序、不重复、无索引。无序指的是存和取有可能不一样
底层:哈希表。哈希表组成:JDK8之前:数组+链表;JDK8之后:数组+链表+红黑树
哈希值:根据hashCode()计算的int整数,确定数据添加到数组哪个位置,然后用equals方法看属性值是否相等。所以存储自定义对象,一定要重写这两个方法
public class Frog {public static void main(String[] args) {Dog do1=new Dog("do1",19);Dog do2=new Dog("do1",19);
// 没有重写hashCode方法,不同对象计算的哈希值不同
// 重写hashCode方法,不同对象属性值相同,计算的哈希值相同System.out.println(do1.hashCode());//没有重写1078694789 重写3088270System.out.println(do2.hashCode());//没有重写1831932724 重写3088270Dog do3=new Dog("do3",19);Dog do4=new Dog("do4",112);HashSet<Dog> hash=new HashSet<>();System.out.println(hash.add(do1));//trueSystem.out.println(hash.add(do2));//falseSystem.out.println(hash.add(do3));//trueSystem.out.println(hash.add(do4));//true//不重写hash方法相同的属性也会打印System.out.println(hash);//[Dog{name = do1, age = 19}, Dog{name = do3, age = 19}, Dog{name = do4, age = 112}]}
}
重写hashCode()不需要自己写
5.2 LinkedHashSet
有序、不重复、无索引
相比HashSet每个元素多了双链表记录存储顺序
5.3 TreeSet
可排序、不重复、无索引
基于红黑树
Dog.java
@Overridepublic int compareTo(Dog o) {//指定排序规则,年龄升序排列return this.age-o.age;}
Frog.java
public class Frog {public static void main(String[] args) {Dog do1=new Dog("do1",16);Dog do2=new Dog("do1",12);Dog do3=new Dog("do3",19);TreeSet<Dog> ts=new TreeSet<>();ts.add(do3);ts.add(do1);ts.add(do2);System.out.println(ts);//[Dog{name = do1, age = 12}, Dog{name = do1, age = 16}, Dog{name = do3, age = 19}]}
}
public class Frog {public static void main(String[] args) {Dog do1=new Dog("do1",16);Dog do2=new Dog("do1",12);Dog do3=new Dog("do3",19);TreeSet<Dog> ts=new TreeSet<>();ts.add(do3);ts.add(do1);ts.add(do2);System.out.println(ts);//[Dog{name = do1, age = 12}, Dog{name = do1, age = 16}, Dog{name = do3, age = 19}]//Comparator比较器排序//存入四个字符串长度排序,长度一样字母排序TreeSet<String> tss=new TreeSet<>(new Comparator<String>() {//lambda前提:compare接口必须是函数接口@Overridepublic int compare(String o1, String o2) {int i=o1.length()-o2.length();//w为0就用默认的匹配规则i=i==0?o1.compareTo(o2):i;return i;}});TreeSet<String> tss1=new TreeSet<>((String o1, String o2)-> {int i=o1.length()-o2.length();//w为0就用默认的匹配规则i=i==0?o1.compareTo(o2):i;return i;});TreeSet<String> tss2=new TreeSet<>((o1, o2)-> {int i=o1.length()-o2.length();//w为0就用默认的匹配规则i=i==0?o1.compareTo(o2):i;return i;});tss.add("aa");tss.add("aab");tss.add("bb");tss.add("a");System.out.println(tss);//[a, aa, bb, aab]}
}
Dog.java
//默认排序,JavaBean类实现Comparable接口
public class Dog implements Comparable<Dog>{private String name;private int age;public Dog() {}public Dog(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo(Dog o) {//指定排序规则,年龄升序排列return this.age-o.age;}
}
6 Arrays
int[] arr={1,2,3,4,5,6};
// 将数组变为字符串,底层:StringBuilder,append方法System.out.println(Arrays.toString(arr));
// 二分查找元素System.out.println(Arrays.binarySearch(arr,4));//索引为3//查找元素不存在,-索引点-1,索引点是应该插入的位置,-1是因为找0返回的是-0,容易误解System.out.println(Arrays.binarySearch(arr,8));//-7int[] new1=Arrays.copyOf(arr,10);//底层System.arraycopy();System.out.println(Arrays.toString(new1));//[1, 2, 3, 4, 5, 6, 0, 0, 0, 0]System.out.println(new1);//[I@41629346//包头不包尾int[] new2=Arrays.copyOfRange(arr,0,4);System.out.println(Arrays.toString(new2));//[1, 2, 3, 4]//底层:循环赋值Arrays.fill(new2,100);System.out.println(Arrays.toString(new2));//[100, 100, 100, 100]Integer[] arri={1,2,3,4,5};//o1-o2 升序 o2-o1 降序//o2 有序序列的元素,o1 无序序列的元素//只能给引用类型数据排序Arrays.sort(arri, new Comparator<>() {@Overridepublic int compare(Integer o1, Integer o2) {return 0;}
});
7 算法题
Dog do1=new Dog("do1",18,180);Dog do2=new Dog("do2",18,181);Dog do3=new Dog("do3",9,176);Dog do4=new Dog("do4",1,121);Dog[] arr={do1,do2,do3,do4};Arrays.sort(arr, new Comparator<Dog>() {
// o1,无序序列的元素,o2有序序列的元素//返回值为负,插入前面,>=0 插入后面@Overridepublic int compare(Dog o1, Dog o2) {double d1=o1.getAge()-o2.getAge();d1=d1==0?o1.getHeight()- o2.getHeight():d1;d1=d1==0?o1.getName().compareTo(o2.getName()):d1;if(d1>0){return 1;}else if(d1<0){return -1;}else{ return 0;}}});System.out.println(Arrays.toString(arr));
//[Dog{name = do4, age = 1, height = 121}, Dog{name = do3, age = 9, height = 176}, Dog{name = do1, age = 18, height = 180}, Dog{name = do2, age = 18, height = 181}]