这篇主要记录了Java中的一些常用数据结构和方法。
List
增删查改
添加List.add
、删除List.remove
、查找List.get
、更改List.set
、存在List.contains
1 2 3 4 5 6 7 8 9 10 List<String> person = new ArrayList <>(); person.add("A" ); person.add("B" ); person.remove(1 ); String result = person.get(0 );System.out.println(result); person.set(0 , "C" ); for (String s : person) System.out.println(s); System.out.println(person.contains("C" ));
改变与替换
.add
将元素放到索引index的位置,原来位置的元素后移。.set
替换index位置的元素。
1 2 person.set(1 , "D" ); person.add(0 , "E" );
查看索引
indexOf
和lastIndexOf
1 2 3 4 5 6 7 person.clear(); person.add("A" ); person.add("B" ); person.add("A" ); person.add("B" ); System.out.println(person.indexOf("A" )); System.out.println(person.lastIndexOf("A" ));
截取
subList
截取区间 [fromIndex,toIndex) 作为新List。
1 2 3 4 5 6 7 8 9 person.clear(); person.add("A" ); person.add("B" ); person.add("C" ); person.add("D" ); person.add("E" ); person = person.subList(1 , 4 ); for (String s : person) System.out.println(s);
对比
equals
对比两个对象,两个对象中的所有元素完全相同。
判空
isEmpty()
去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 List<String> lst1 = new ArrayList <>(); lst1.add("aa" ); lst1.add("dd" ); lst1.add("ss" ); lst1.add("aa" ); lst1.add("ss" ); for (int i = 0 ; i < lst1.size() - 1 ; i++) { for (int j = lst1.size() - 1 ; j > i; j--) { if (lst1.get(j).equals(lst1.get(i))) { lst1.remove(j); } } } System.out.println(lst1); List<String> lst2 = new ArrayList <>(); for (String s : lst1) { if (Collections.frequency(lst2, s) < 1 ) { lst2.add(s); } } System.out.println(lst2);
https://blog.csdn.net/Barcon/article/details/82628120
PriorityQueue
概述
优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序,可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类。对于基本数据类型的包装器类,优先队列中元素默认排列顺序是升序排列,但对于自己定义的类来说,需要自己定义比较器。
常用方法
1 2 3 4 5 peek() poll() add() size() isEmpty()
使用
队列保存的是基本数据类型的包装类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 static Comparator<Integer> cmp = new Comparator <Integer>() { public int compare (Integer e1, Integer e2) { return e2 - e1; } }; public static void main (String[] args) { Queue<Integer> q = new PriorityQueue <>(); q.add(3 ); q.add(2 ); q.add(4 ); while (!q.isEmpty()) { System.out.print(q.poll()+" " ); } Queue<Integer> qq = new PriorityQueue <>(cmp); qq.add(3 ); qq.add(2 ); qq.add(4 ); while (!qq.isEmpty()) { System.out.print(qq.poll()+" " ); } }
保存了自定义类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Node { public Node (int chang,int kuan) { this .chang=chang; this .kuan=kuan; } int chang; int kuan; } public class Test { static Comparator<Node> cNode=new Comparator <Node>() { public int compare (Node o1, Node o2) { if (o1.chang!=o2.chang) return o1.chang-o2.chang; else return o2.kuan-o1.kuan; } }; public static void main (String[] args) { Queue<Node> q=new PriorityQueue <>(cNode); Node n1=new Node (1 , 2 ); Node n2=new Node (2 , 5 ); Node n3=new Node (2 , 3 ); Node n4=new Node (1 , 2 ); q.add(n1); q.add(n2); q.add(n3); Node n; while (!q.isEmpty()) { n=q.poll(); System.out.println("长: " +n.chang+" 宽:" +n.kuan); } } }
遍历
PriorityQueue的iterator()不保证以任何特定顺序遍历队列元素。若想按特定顺序遍历,先将队列转成数组,然后排序遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 Queue<Integer> q = new PriorityQueue <>(cmp); int [] nums= {2 ,5 ,3 ,4 ,1 ,6 };for (int i:nums){ q.add(i); } Object[] nn=q.toArray(); Arrays.sort(nn); for (int i=nn.length-1 ;i>=0 ;i--) System.out.print((int )nn[i]+" " );
比较器降序说明
1 2 3 4 5 6 7 8 Comparator<Object> cmp = new Comparator <Object>() { public int compare (Object o1, Object o2) { return o1-o2; return o2-o1; } };
数据流中的中位数
下面再来看这道题
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
普通解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public : vector<int > s; void Insert (int num) { s.push_back (num); } double GetMedian () { sort (s.begin (), s.end ()); int i = s.size (); if (i % 2 != 0 ) return s[(i + 1 ) / 2 - 1 ]; else return ((double )s[i / 2 - 1 ] + (double )s[i / 2 ]) / 2 ; } };
生成一个大顶堆和小顶堆,维持大顶堆的数都小于等于小顶堆的数,且二者个数相等或者相差为1,平均数即在两个栈顶的数之中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { priority_queue<int , vector<int >, less<int > > left; priority_queue<int , vector<int >, greater<int > > right; public : void Insert (int num) { if (left.empty () || num <= left.top ()) left.push (num); else right.push (num); if (left.size () == right.size () + 2 ) right.push (left.top ()), left.pop (); if (left.size () + 1 == right.size ()) left.push (right.top ()), right.pop (); } double GetMedian () { return left.size () == right.size () ? (left.top () + right.top ()) / 2.0 : left.top (); } };
StringBuffer
概述
当对字符串进行修改时候,需要使用StringBuffer和StringBuilder类。不同于String,他们可以被多次修改而不产生新的对象。StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
String适用于少量的字符串操作的情况,StringBuilder适用于单线程下在字符缓冲区进行大量操作的情况,StringBuffer适用多线程下在字符缓冲区进行大量操作的情况。
使用
toString()
1 2 StringBuffer s1 = new StringBuffer ();s1.toString();
append()
1 2 StringBuffer s1 = new StringBuffer ().append("bbb" );s1.append("aaa" );
charAt()
1 System.out.println(s1.charAt(3 ));
deleteCharAt()
1 2 StringBuffer s1 = new StringBuffer ().append("bbbaaa" );s1.deleteCharAt(3 );
delete()
删除从开始索引到结束索引的字符串。
1 2 StringBuffer s1 = new StringBuffer ().append("bbbaaa" );s1.delete(2 , 4 );
insert()
在指定索引位置之前插入字符串。
1 2 StringBuffer s1 = new StringBuffer ().append("bbbaaa" );s1.insert(2 ,"cc" );
indexOf()
返回指定字符串的开始字符索引位置,还可以从某个字符索引位置开始向后匹配,没有找到匹配的就会返回-1。
1 2 3 4 StringBuffer s1 = new StringBuffer ().append("bbbaaa" );System.out.println(s1.indexOf("ba" )); System.out.println(s1.indexOf("ba" ,2 )); System.out.println(s1.indexOf("mn" ));
lastIndexOf()
和indexOf()的用法一样,只不过是从后往前匹配,也支持从指定索引开始从后往前去匹配。
1 2 3 4 StringBuffer s1 = new StringBuffer ().append("bbb" );s1.append("aaa" ); System.out.println(s1.toString()); System.out.println(s1.lastIndexOf("b" ,5 ));
reverse()
1 2 3 StringBuffer s1 = new StringBuffer ().append("bbbaaa" );System.out.println(s1.reverse()); System.out.println(s1.toString());
length()
返回长度。
HashMap
概述
在JDK1.6,JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用位桶+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。参考链接
HashMap的实现是不同步的,这意味着它不是线程安全的。它的key,value都可以是null。此外,HashMap中的映射不是有序的。
HashMap的实例有两个参数影响其性能:“初始容量”和“加载因子”。初始容量是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。通常默认加载因子是0.75,这是在时间和空间成本上寻求一种折衷。
使用
构造函数
1 2 3 4 5 6 7 8 HashMap() HashMap(int capacity) HashMap(int capacity, float loadFactor) HashMap(Map<? extends K , ? extends V > map)
API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void clear () Object clone () boolean containsKey (Object key) boolean containsValue (Object value) Set<Entry<K, V>> entrySet () V get (Object key) V getOrDefault (Object key, V value) boolean isEmpty () Set<K> keySet () V put (K key, V value) void putAll (Map<? extends K, ? extends V> map) V remove (Object key) int size () Collection<V> values () V replace (key,val)
遍历
遍历HashMap的键值对
第一步:根据entrySet()获取HashMap的“键值对”的Set集合,效率高。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
1 2 3 4 5 6 7 8 9 10 Integer integ = null ;Iterator iter = map.entrySet().iterator();while (iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); key = (String)entry.getKey(); integ = (Integer)entry.getValue(); }
遍历HashMap的键
第一步:根据keySet()获取HashMap的“键”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
1 2 3 4 5 6 7 8 9 10 11 String key = null ;Integer integ = null ;Iterator iter = map.keySet().iterator();while (iter.hasNext()) { key = (String)iter.next(); integ = (Integer)map.get(key); }
遍历HashMap的值
第一步:根据value()获取HashMap的“值”的集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
1 2 3 4 5 6 7 Integer value = null ;Collection c = map.values();Iterator iter= c.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
String
1 2 3 4 5 6 7 String x="fmn" ; x.toUpperCase(); String y=x.replace('f' ,'F' ); String x="fmn" ; “fmn”是在常量池里的不可变对象。 x.toUpperCase(); 在堆中new 一个"FMN" 对象,但无任何引用指向它。 String y=x.replace('f' ,'F' ); 在堆中 new 一个"Fmn" 对象,y指向它。 y=y+"wxy" ; 在堆中 重新new 一个"Fmnwxy" 对象, 修改y指向,现在y指向它。
substring()