Java各种数据结构实现方式

在这里插入图片描述
容器分为collection和map两种
在这里插入图片描述
在这里插入图片描述

Collection通用方法:
size();
isEmpty();//和String一样
contains();//list set里都有contains
iterator();
add();
remove();
removeAll();
equals();
hashCode();
clear()
// 反转lists
Collections.reverse(lists); lists自己变了自己反了
Map通用方法:https://blog.csdn.net/iteye_11587/article/details/82680055
  int size();

    /**
     * Returns <tt>true</tt> if this map contains no key-value mappings.
     *Map是否为null,即没有k-v
     * @return <tt>true</tt> if this map contains no key-value mappings
     */
    boolean isEmpty();

    /**
     如果Map中包含key,则返回true。当且仅当,map存在唯一的key时,才返回true
     */
    boolean containsKey(Object key);

    /**
     * 当队列中有一个或多个key对应的值为value,则返回true,这个操作的时间复杂度是线性的O(n),
     在大多数的Map实现类中
     */
    boolean containsValue(Object value);

    /**
     * 返回key对应值value,如果没有对应的key,则返回为null。
     *如果Map允许Null值的存在,则返回null是不必要的。
     */
    V get(Object key);

    // Modification Operations

    /**
     将一个k-v对,放入到Map中,如果Map已经存在对应的Key,则新的值,将覆盖旧值
     */
    V put(K key, V value);

    /**
     *从Map移除对应的k-v对
     */
    V remove(Object key);


    // Bulk Operations

    /**
     copy一个Map到当前Map,即遍历Copy Map的k-v,放入到当前Map中
     */
    void putAll(Map<? extends K, ? extends V> m);

    /**
     * 从当前Map中,移除所有的k-v对
     */
    void clear();


    // Views

    /**
     返回Map中key的视图Set,key Set与Map相关联,当Map改变时,将会影响Key set,
     反之亦然。我们可以通过key Set的Iterator移除Map中的k-v
     * @return a set view of the keys contained in this map
     */
    Set<K> keySet();

    /**
     返回Map中value的视图Collection,这Collection与Map相关联,当Map改变时,
     直接映射Value的视图Collection,反之亦然。
     */
    Collection<V> values();

    /**
     返回Map中所有K-v对的视图Set,k-v Set与Map相关联,当Map改变时,将会影响k-v set,
     反之亦然。我们可以通过k-v Set的Iterator移除Map中的k-v
     */
    Set<Map.Entry<K, V>> entrySet();

    /**
     Entry表示一个k-v对,Map.entrySet方法返回的k-v,就是Entry。从获取一个Map.Entry
     的方法,只有从entrySet()返回的集合Set<Map.Entry<K, V>>的iterator。
     Map.Entry仅仅在遍历iteration的期间有效的,进一步说,当Map通过setValue操作,
     修改 Map.Entry时,iteration的返回值是不确定的
     */
    interface Entry<K,V> {
        /**
	 返回k-v值对entry的key
         */
        K getKey();

        /**
	 返回k-v值对,entry的值,如果entry通过iterator从Map中移除,则返回结果是不确定的
         */
        V getValue();

        /**
         *
	 设置k-v值对,entry的值,如果在写到Map的过程中,
	 entry被iterator从Map中移除,则返回结果是不确定的。

         */
        V setValue(V value);
        boolean equals(Object o);
        int hashCode();
HashMap
void clear();    删除所有的映射
boolean containsKey(Object key)  如果此映射包含指定键的映射,则返回true
boolean containsValue(Object value)  如果将一个或多个键映射到指定值,则返回true
V get(Object key)   返回到指定键所映射的值,或 null如果此映射包含该键的映射
boolean isEmpty()   如果此地图不包含键值映射,则返回 true  
V put(K key, V value)   将指定的值与此映射中的指定键相关联
V remove(Object key)  从该地图中删除指定键的映射(如果存在)
V replace(K key, V value)   只有当目标映射到某个值时,才能替换指定键的条目 
int size()   返回此地图中键值映射的数量
List接口比起Collection多出:
get();
set();
indexOf();
sort();
Stack<Integer> stack = new Stack<Integer>();
Deque<Integer> stack=new LinkedList<Integer>();
比起Queue独有方法,DequeQueue子接口,有Queue的全部方法:
push();链表头插
pop();删除链表头且返回头
boolean empty() 测试堆栈是否为空。
Object peek( )查看堆栈顶部的对象,但不从堆栈中移除它。
int search(Object element) 返回对象在堆栈中的位置,以 1 为基数。
队列
Queue<String> queue=new LinkedList<String>();
常用方法:
offer();链表尾插(满时只返回false不抛出异常)
poll();删除链表头且返回头(空时只返回null不抛出异常)
peek();查询链表头(不删除头)(空时只返回null不抛出异常)
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
    @Override
    public int compare(Integer i1,Integer i2){
        return i2-i1;
    }
});
想换当前a b则返回正数(反过来是大顶堆,想换回正)
      String[] x = new String[]{"a", "b"};
      Arrays.sort(x, (a, b)->{
        if(a.equals("a"))
          return -1;
        return 1;
      });
      结果 a b没换序
sort可以理解为永远的升序
compareTo返回数字理解
如果参数字符串等于此字符串,则返回值 0;
如果此字符串小于字符串参数,则返回一个小于 0 的值;这个就是小于号
如果此字符串大于字符串参数,则返回一个大于 0 的值。

PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。

  插入方法(offer()poll()remove()add() 方法)时间复杂度为O(log(n)) ;
  remove(Object)contains(Object) 时间复杂度为O(n);
  检索方法(peek、element 和 size)时间复杂度为常量。

Integer.MAX_VALUE
Integer.MIN_VALUE


Map<Integer,String> map = new HashMap<>();   
  
    Iterator it = map.entrySet().iterator();   
  
    while (it.hasNext()) {   
  
        Map.Entry entry = (Map.Entry) it.next();   
  
        Object key = entry.getKey();   
  
        Object value = entry.getValue(); 
------------------------------------
for(Map.Entry<Integer,Integer> m:map.entrySet())
				{
					if(arr[i]==(int)m.getKey())
						map.put((int)m.getKey(),(int)m.getValue()+1);
				}
————————————————
版权声明:本文为CSDN博主「吴孟达」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/exceptional_derek/article/details/9715445
int i = Integer.valueOf(my_str);
String s = String.valueOf(i);
//i也可以是CharArray

菜鸟教程Java String int互相转换


   @param args
   String类的获取功能
   1.int length();获取字符串的长度
   2.char charAt(int index);获取指定索引位置的字符
   3.int indexOf(int ch);返回指定字符在此字符串中第一次出现处的索引
   4.int indexOf(String str);返回指定字符串在此字符串中第一次出现处的索引
   5.int indexOf(int ch,int fromIndex);返回指定字符在此字符串中从指定位置后第一次出现处的索引
   6.int indexOf(String str,int fromIndex);返回指定字符串在此字符串中从指定位置后第一次出现处的索引
   7.lastIndexOf(char ch)从后向前找,第一次出现的字符
   8.记得将返回值赋给原来string,这个函数只更改返回值不更改被传进去的string String substring(int start);从指定位置开始截取字符串,默认到末尾
   9.String substring(int start,int end);从指定位置开始到指定位置结束截取字符串
   10.charAt():返回指定索引处char值
   11.length()
   12. split(String regex, int limit)regex -- 正则表达式分隔符。
limit -- 分割的份数。
    13.	char[] toCharArray()将此字符串转换为一个新的字符数组。
    14.	contains(CharSequence chars)判断是否包含指定的字符系列。
    15.	isEmpty()判断字符串是否为空。
    16.	请注意,您的方法对于非常大的整数可能会失败,因为将两个有效ints串联可能会产生一个太大而int无法容纳的数字。Integer.parseInt(s1 + s2) - Integer.parseInt(s2 + s1)等价于您可以(s1+s2).compareTo(s2+s1)被减数.compareTo(减数)取而代之的是进行字典比较,这与相同长度数字的数字比较相同。https://stackoverflow.com/questions/29583035/no-suitable-method-found-for-sortint-anonymous-comparatorinteger

String菜鸟教程

String Char相互转换
String转换为charJava中将String转换为char是非常简单的。
1. 使用String.charAt(index)(返回值为char)可以得到String中某一指定位置的char2. 使用String.toCharArray()(返回值为char[])可以得到将包含整个Stringchar数组。这样我们就能够使用从0开始的位置索引来访问string中的任意位置的元素。
char转string六种方法
1. String s = String.valueOf('c'); //效率最高的方法

2. String s = String.valueOf(new char[]{'c'}); //将一个char数组转换成String

3. String s = Character.toString('c');
// Character.toString(char)方法实际上直接返回String.valueOf(char)

4. String s = new Character('c').toString();

5. String s = "" + 'c';
// 虽然这个方法很简单,但这是效率最低的方法
// Java中的String Object的值实际上是不可变的,是一个final的变量。
// 所以我们每次对String做出任何改变,都是初始化了一个全新的String Object并将原来的变量指向了这个新String。
// 而Java对使用+运算符处理String相加进行了方法重载。
// 字符串直接相加连接实际上调用了如下方法:
// new StringBuilder().append("").append('c').toString();


6. String s = new String(new char[]{'c'});
默认值

在这里插入图片描述

以二分查找的有序集合复杂度为ologn,相当于C++的set集合,c++lowerbound:二分查找一个有序数列,返回第一个>=x的书,如果没找到则返回迭代器末尾位置
TreeSet
是一个有序的集合,它的作用是提供有序的Set集合。
HashSet无序 线程不安全 无重复值
TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, java.io.Serializable接口。
TreeSet 继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
TreeSet 实现了Cloneable接口,意味着它能被克隆。
TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。
TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。
TreeSet为基本操作(add、remove 和 contains)提供受保证的 log(n) 时间开销。
另外,TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。
 
TreeSet的构造函数

// 默认构造函数。使用该构造函数,TreeSet中的元素按照自然排序进行排列。
TreeSet()

// 创建的TreeSet包含collection
TreeSet(Collection<? extends E> collection)

// 指定TreeSet的比较器
TreeSet(Comparator<? super E> comparator)

// 创建的TreeSet包含set
TreeSet(SortedSet<E> set)

TreeSetAPI

boolean                   add(E object)
boolean                   addAll(Collection<? extends E> collection)
void                      clear()
Object                    clone()
boolean                   contains(Object object)
E                         first()
boolean                   isEmpty()
E                         last()
E                         pollFirst()
E                         pollLast()
E                         lower(E e)
E                         floor(E e)
E                         ceiling(E e)
E                         higher(E e)
boolean                   remove(Object object)
int                       size()
Comparator<? super E>     comparator()
Iterator<E>               iterator()
Iterator<E>               descendingIterator()
SortedSet<E>              headSet(E end)
NavigableSet<E>           descendingSet()
NavigableSet<E>           headSet(E end, boolean endInclusive)
SortedSet<E>              subSet(E start, E end)
NavigableSet<E>           subSet(E start, boolean startInclusive, E end, boolean endInclusive)
NavigableSet<E>           tailSet(E start, boolean startInclusive)
java.util.TreeSet.tailSet(E fromElement,boolean inclusive) 返回
一组大于或等于(如果包含,则为true)指定元素的元素。
SortedSet<E>              tailSet(E start)
说明:
(01) TreeSet是有序的,并且没有重复元素的Set集合,因此支持add、remove、get等方法。
(02)NavigableSet一样,TreeSet的导航方法大致可以区分为两类,一类时提供元素项的导航方法,返回某个元素;另一类时提供集合的导航方法,返回某个集合。
lower、floor、ceiling 和 higher 分别返回小于、小于等于、大于等于、大于给定元素的元素,如果不存在这样的元素,则返回 null。
默认是升序排列如果要想使集合中的顺序按照降序排列的话需要用到TreeSetdescendingSet()方法.
———————————————
版权声明:本文为CSDN博主「南     墙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a1439775520/article/details/95373610

new Comparator(){
         public int compare(Object obj1,Object obj2){
          if(obj1 instanceof Employee && obj2 instanceof Employee){
                Employee o1 = (Employee) obj1;
                Employee o2 = (Employee) obj2;
                int year = o1.getBirthday().getYear() - o2.getBirthday().getYear();
                if(year == 0){
                   int month = o1.getBirthday().getMonth()-(o2.getBirthday().getMonth());
                   if(month == 0){
                       int day = o1.getBirthday().getDay()-(o2.getBirthday().getDay());
                        return day;
                   }else{
                     return month;
                   }
                }else{
                 return year;
                }
          }
          return 0;
         }
       };
————————————————
版权声明:本文为CSDN博主「Sue12347」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Sue12347/article/details/80267866
// 第一种
DecimalFormat df = new DecimalFormat("#0.00");
float data;
data = sc.nextFloat();
System.out.println(df.format(data));
 
// 第二种,模仿c语言的输出方式
System.out.printf("%.2f\n", data);
 
// 第三种
System.out.println(String.format("%.2f", data));
注意和c/c++不同的是double对应的数据类型是 %f,而非%lf;

List
在这里插入图片描述

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Scanner;
 
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 第一种
DecimalFormat df = new DecimalFormat("#0.00");
float data;
data = sc.nextFloat();
System.out.println(df.format(data));
 
// 第二种,模仿c语言的输出方式
System.out.printf("%.2f\n", data);
 
// 第三种
System.out.println(String.format("%.2f", data));
 
}
 
}

注意和c/c++不同的是double对应的数据类型是 %f,而非%lf;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ValueOf
public static String valueOf(boolean b)返回 boolean 参数的字符串表示形式。
public static String valueOf(char c)返回 char 参数的字符串表示形式。
public static String valueOf(int i)返回 int 参数的字符串表示形式。
public static String valueOf(long l)返回 long 参数的字符串表示形式。
public static String valueOf(float f)返回 float 参数的字符串表示形式。
public static String valueOf(double d)返回 double 参数的字符串表示形式。
public static Boolean valueOf(boolean b)返回一个表示指定 boolean 值的 Boolean 实例。如果指定的 boolean 值为 true,则此方法返回 Boolean.TRUE;如果为 false,则返回 Boolean.FALSEpublic static Boolean valueOf(String s)返回一个用指定的 String 表示值的 Boolean 值。如果 String 参数不为 null 且在忽略大小写时等于 "true",则返回的 Boolean 表示 true 值。
例子:Boolean.valueOf("True") 返回 true。
例子:Boolean.valueOf("yes") 返回 falsepublic static Integer valueOf(String s)
                       throws NumberFormatException返回保持指定的 String 的值的 Integer 对象。
public static Integer valueOf(int i)返回一个表示指定的 int 值的 Integer 实例

就是类型之间的转换。
目前在Java中数据拷贝提供了如下方式:

clone
System.arraycopy
Arrays.copyOf
Arrays.copyOfRange
下面分别介绍他们的用法
1、clone 方法
clone方法是从Object类继承过来的,基本数据类型(intbooleancharbyteshortfloatdoublelong)都可以直接使用clone方法进行克隆,注意String类型是因为其值不可变所以才可以使用。

int 类型示例
int[] a1 = {1, 3};
int[] a2 = a1.clone();

a1[0] = 666;
System.out.println(Arrays.toString(a1));   //[666, 3]
System.out.println(Arrays.toString(a2));   //[1, 3]
String类型示例
String[] a1 = {"a1", "a2"};
String[] a2 = a1.clone();

a1[0] = "b1"; //更改a1数组中元素的值
System.out.println(Arrays.toString(a1));   //[b1, a2]
System.out.println(Arrays.toString(a2));   //[a1, a2]
2System.arraycopy
System.arraycopy方法是一个本地的方法,源码里定义如下:

public static native void arraycopy(Object src, int srcPos, Object dest, int desPos, int length)
1
其参数含义为:

(原数组, 原数组的开始位置, 目标数组, 目标数组的开始位置, 拷贝个数)
1
用法示例
int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = new int[10];

System.arraycopy(a1, 1, a2, 3, 3);
System.out.println(Arrays.toString(a1)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(a2)); // [0, 0, 0, 2, 3, 4, 0, 0, 0, 0]

当使用这个方法的时候,需要复制到一个已经分配内存单元的数组。

3Arrays.copyOf
Arrays.copyOf底层其实也是用的System.arraycopy 源码如下:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

参数含义:

(原数组,拷贝的个数)
1
用法示例:
int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = Arrays.copyOf(a1, 3);

System.out.println(Arrays.toString(a1)) // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(a2)) // [1, 2, 3]

使用该方法无需我们事先使用new关键字对对象进行内存单元的分配

4Arrays.copyOfRange
Arrays.copyOfRange底层其实也是用的System.arraycopy,只不过封装了一个方法

public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}

参数含义

(原数组,开始位置,拷贝的个数)

用法示例:

int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = Arrays.copyOfRange(a1, 0, 1);

System.out.println(Arrays.toString(a1)) // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(a2)) // [1]

最后需要注意的是基本类型的拷贝是不影响原数组的值的,如果是引用类型,就不能在这用了,因为数组的拷贝是浅拷贝,对于基本类型可以,对于引用类型是不适合的。

5、那么如何实现对象的深度拷贝呢?
5.1 实现Cloneable接口
实现Cloneable接口,并重写clone方法,注意一个类不实现这个接口,直接使用clone方法是编译通不过的。

/**
 * Created by Joe on 2018/2/13.
 */
public class Dog implements Cloneable {
    private String id;
    private String name;

	public Dog(String id, String name) {
        this.id = id;
        this.name = name;
    }

    // 省略 getter 、 setter 以及 toString 方法

    @Override
    public Dog clone() throws CloneNotSupportedException {
        Dog dog = (Dog) super.clone();

        return dog;
    }
}

示例:

Dog dog1 = new Dog("1", "Dog1");
Dog dog2 = dog1.clone();

dog2.setName("Dog1 changed");

System.out.println(dog1); // Dog{id='1', name='Dog1'}
System.out.println(dog2); // Dog{id='1', name='Dog1 changed'}

5.2 组合类深拷贝
如果一个类里面,又引用其他的类,其他的类又有引用别的类,那么想要深度拷贝必须所有的类及其引用的类都得实现Cloneable接口,重写clone方法,这样以来非常麻烦,简单的方法是让所有的对象实现序列化接口(Serializable),然后通过序列化反序列化的方法来深度拷贝对象。

public Dog myClone() {
	Dog dog = null;

	try {
		//将对象序列化成为流,因为写在流是对象里的一个拷贝
		//而原始对象扔在存在JVM中,所以利用这个特性可以实现深拷贝
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
		objectOutputStream.writeObject(this);

		//将流序列化为对象
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
		dog = (Dog) objectInputStream.readObject();
	} catch (IOException | ClassNotFoundException e) {
		e.printStackTrace();
	}

	return dog;
}

总结:
本文介绍了关于Java里面的数组拷贝的几种方式和用法,并给出了如何在Java里面实现对象的深度拷贝,注意除非必需,一般情况下不要使用对象的深度拷贝,因为性能较差。除了自己实现深度拷贝的功能外,网上也有一些开源的工具类也集成了这些功能,如Apache Common Lang3,但原理都大同小异,感兴趣的同学可以自己去学习下。
————————————————
版权声明:本文为CSDN博主「寒沧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011669700/article/details/79323251
ArrayList转数组

List stringList = new ArrayList<>();
String[] stringArray = stringList.toArray(new String[stringList.size()]);//这里一定要指定数组类型,否则就会转换成object数组

Java compareTo

TreeSet字典序排序

TreeSet和HashSet的区别在于, TreeSet可以进行排序, 默认使用字典顺序排序, 也可以进行自定义排序

TreeSet<String> ts = new TreeSet<String>(new Comparator<String>()      
           {
            @Override
            public int compare(String o1, String o2) {
                int num = o1.compareTo(o2);//小顶堆也即是字典序
                return num;
            }
        });
        ts.add("asdas");
        ts.add("sdf");
        ts.add("dfgdf");
        ts.add("bgt");
        ts.add("tyu");
        ts.add("xcv");
        ts.add("nbmbn");
        ts.add("tyut");
        System.out.println(ts);
        结果:[asdas, bgt, dfgdf, nbmbn, sdf, tyu, tyut, xcv]
         TreeSet<String> ts = new TreeSet<String>();
         和上述结果一样,说明treeset默认即为字典序,
         o2.compareTo(o1)反过来即为大顶堆,字典序逆序,
         和优先队列是一样的。
         比如0,1比较返回-1就是小顶堆就是原来顺序
         所以返回正数就是调换两个元素顺序
HashSet遍历

由于Set集合中不允许存在重复值,因此可以使用Set集合中的addAll()方法,将Collection集合添加到Set集合中并除掉重复值。

1.迭代遍历:
Set set = new HashSet();
Iterator it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}

2.for循环遍历:
for (String str : set) {
System.out.println(str);
}

优点还体现在泛型 假如 set中存放的是Object

Set set = new HashSet();
for循环遍历:
for (Object obj: set) {
if(obj instanceof Integer){
int aa= (Integer)obj;
}else if(obj instanceof String){
String aa = (String)obj
}}
对map集合进行排序(TreeMap 默认排序规则:按照key的字典顺序来排序(升序)(小顶堆))
今天做统计时需要对X轴的地区按照地区代码(areaCode)进行排序,由于在构建XMLData使用的map来进行数据统计的,所以在统计过程中就需要对map进行排序。

一、简单介绍Map
       在讲解Map排序之前,我们先来稍微了解下map。map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等。其中这四者的区别如下(简单介绍):

       HashMap:我们最常用的Map,它根据key的HashCode 值来存储数据,根据key可以直接获取它的Value,同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的ValueNull。非同步的。

      TreeMap: 能够把它保存的记录根据key排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。

      Hashtable:HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

      LinkedHashMap: 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。

 

二、Map排序
TreeMap
      TreeMap默认是升序的,如果我们需要改变排序方式,则需要使用比较器:ComparatorComparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1,小于、等于或者大于o2分别返回负整数、0或者正整数。如下:
      public class TreeMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<String, String>(
                new Comparator<String>() {
                    public int compare(String obj1, String obj2) {
                        // 降序排序
                        return obj2.compareTo(obj1);
                    }
                });
        map.put("c", "ccccc");
        map.put("a", "aaaaa");
        map.put("b", "bbbbb");
        map.put("d", "ddddd");
        
        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            System.out.println(key + ":" + map.get(key));
        }
    }
}
   运行结果如下:

      d:ddddd 
      c:ccccc 
      b:bbbbb 
      a:aaaaa

      上面例子是对根据TreeMap的key值来进行排序的,但是有时我们需要根据TreeMap的value来进行排序。对value排序我们就需要借助于Collectionssort(List<T> list, Comparator<? super T> c)方法,该方法根据指定比较器产生的顺序对指定列表进行排序。但是有一个前提条件,那就是所有的元素都必须能够根据所提供的比较器来进行比较。如下:
      public class TreeMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<String, String>();
        map.put("d", "ddddd");
        map.put("b", "bbbbb");
        map.put("a", "aaaaa");
        map.put("c", "ccccc");
        
        //这里将map.entrySet()转换成list
        List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
        //然后通过比较器来实现排序
        Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
            //升序排序
            public int compare(Entry<String, String> o1,
                    Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
            
        });
        
        for(Map.Entry<String,String> mapping:list){ 
               System.out.println(mapping.getKey()+":"+mapping.getValue()); 
          } 
    }
}
      运行结果

      a:aaaaa 
      b:bbbbb 
      c:ccccc 
      d:ddddd

 

HashMap
      我们都是HashMap的值是没有顺序的,他是按照key的HashCode来实现的。对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeMap的value排序,我们一样的也可以实现HashMap的排序。
      public class HashMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("c", "ccccc");
        map.put("a", "aaaaa");
        map.put("b", "bbbbb");
        map.put("d", "ddddd");
        
        List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
        Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
            //升序排序
            public int compare(Entry<String, String> o1,
                    Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
            
        });
        
        for(Map.Entry<String,String> mapping:list){ 
               System.out.println(mapping.getKey()+":"+mapping.getValue()); 
          } 
     }
}
运行结果

      a:aaaaa 
      b:bbbbb 
      c:ccccc 
      d:ddddd

TreeMap转载自该篇文章

Lambda

Arrays.sort()使用
//被排序的字符串数组
String[] months = {"January","February","March","April","May","June","July","August","September","October","December"};
//按字符串长度排序
//1.
Arrays.sort(months, (a, b) -> Integer.signum(a.length() - b.length()));
//2.
Arrays.sort(months, Comparator.comparingInt(String::length));
//3.
Arrays.sort(months, (a, b) -> a.length() - b.length());//表示若这表达式大于0则a放前面
//4.
Arrays.sort(months,(String a, String b) -> { return Integer.signum(a.length() - b.length()); });

Java 双端队列Deque

在这里插入图片描述

两种初始化方式:
Deque<Integer> snack = new ArrayDeque<>();
LinkedList<Integer> list = new LinkedList<Integer>();
队列的offer poll peek加上FirstLast
双向队列操作
插入元素
addFirst(): 向队头插入元素,如果元素为空,则发生NPE

addLast(): 向队尾插入元素,如果为空,则发生NPE

offerFirst(): 向队头插入元素,如果插入成功返回true,否则返回false

offerLast(): 向队尾插入元素,如果插入成功返回true,否则返回false

移除元素
removeFirst(): 返回并移除队头元素,如果该元素是null,则发生NoSuchElementException

removeLast(): 返回并移除队尾元素,如果该元素是null,则发生NoSuchElementException

pollFirst(): 返回并移除队头元素,如果队列无元素,则返回null

pollLast(): 返回并移除队尾元素,如果队列无元素,则返回null

获取元素
getFirst(): 获取队头元素但不移除,如果队列无元素,则发生NoSuchElementException

getLast(): 获取队尾元素但不移除,如果队列无元素,则发生NoSuchElementException

peekFirst(): 获取队头元素但不移除,如果队列无元素,则返回null

peekLast(): 获取队尾元素但不移除,如果队列无元素,则返回null

栈操作
pop(): 弹出栈中元素,也就是返回并移除队头元素,等价于removeFirst(),如果队列无元素,则发生NoSuchElementException

push(): 向栈中压入元素,也就是向队头增加元素,等价于addFirst(),如果元素为null,则发生NPE,如果栈空间受到限制,则发生IllegalStateException

应用场景
满足FIFO场景时
满足LIFO场景时,曾经在解析XML按标签时使用过栈这种数据结构,但是却选择Stack类,如果在进行栈选型时,更推荐使用Deque类,应为Stack是线程同步
主要实现
ArrayDeque: 基于数组实现的线性双向队列
LinkedList: 基于链表实现的链式双向队列

特性:

插入、删除、获取操作支持两种形式:快速失败和返回null或true/false
既具有FIFO特点又具有LIFO特点,即是队列又是栈
不推荐插入null元素,null作为特定返回值表示队列为空
未定义基于元素相等的equals和hashCode

转载自 deque

String大小写字母转换

String str = “helloworld” ;
System.out.println(str.toUpperCase());//让str里面的字符全部大写
System.out.println(str.toLowerCase());//让str里面的字符全部小写

Object compareTo
// 2.重写compareTo(obj)的规则:
// 如果当前对象this大于形参对象obj,则返回正整数,
// 如果当前对象this小于形参对象obj,则返回负整数,
// 如果当前对象this等于形参对象obj,则返回零。

在本文中,我们将通过示例讨论在 Java 上遍历 HashMap 的五种最佳方法。
1.使用 Iterator 遍历 HashMap EntrySet
2.使用 Iterator 遍历 HashMap KeySet
3.使用 For-each 循环迭代 HashMap
4.使用 Lambda 表达式遍历 HashMap
5.使用 Stream API 遍历 HashMap
 
1. 使用 Iterator 遍历 HashMap EntrySet
package com.java.tutorials.iterations;  
 
import java.util.HashMap;  
import java.util.Iterator;  
import java.util.Map;  
import java.util.Map.Entry;  
 
/**  
 * 在 Java 中遍历 HashMap 的5种最佳方法  
 * @author Ramesh Fadatare  
 *  
 */  
public class IterateHashMapExample {  
    public static void main(String[] args) {  
        // 1. 使用 Iterator 遍历 HashMap EntrySet  
        Map < Integer, String > coursesMap = new HashMap < Integer, String > ();  
        coursesMap.put(1, "C");  
        coursesMap.put(2, "C++");  
        coursesMap.put(3, "Java");  
        coursesMap.put(4, "Spring Framework");  
        coursesMap.put(5, "Hibernate ORM framework");  
 
        Iterator < Entry < Integer, String >> iterator = coursesMap.entrySet().iterator();  
        while (iterator.hasNext()) {  
            Entry < Integer, String > entry = iterator.next();  
            System.out.println(entry.getKey());  
            System.out.println(entry.getValue());  
        }  
    }  
}
 
2. 使用 Iterator 遍历 HashMap KeySet
package com.java.tutorials.iterations;  
 
import java.util.HashMap;  
import java.util.Iterator;  
import java.util.Map;  
 
/**  
 * 在 Java 中遍历 HashMap 的5种最佳方法  
 * @author Ramesh Fadatare  
 *  
 */  
public class IterateHashMapExample {  
    public static void main(String[] args) {  
        Map < Integer, String > coursesMap = new HashMap < Integer, String > ();  
        coursesMap.put(1, "C");  
        coursesMap.put(2, "C++");  
        coursesMap.put(3, "Java");  
        coursesMap.put(4, "Spring Framework");  
        coursesMap.put(5, "Hibernate ORM framework");  
 
        // 2. 使用 Iterator 遍历 HashMap KeySet  
        Iterator < Integer > iterator = coursesMap.keySet().iterator();  
        while (iterator.hasNext()) {  
            Integer key = iterator.next();  
            System.out.println(key);  
            System.out.println(coursesMap.get(key));  
        }  
    }  
}
 
3. 使用 For-each 循环遍历 HashMap
package com.java.tutorials.iterations;  
 
import java.util.HashMap;  
import java.util.Map;  
 
/**  
 * 在 Java 中遍历 HashMap 的5种最佳方法  
 * @author Ramesh Fadatare  
 *  
 */  
public class IterateHashMapExample {  
    public static void main(String[] args) {  
        Map < Integer, String > coursesMap = new HashMap < Integer, String > ();  
        coursesMap.put(1, "C");  
        coursesMap.put(2, "C++");  
        coursesMap.put(3, "Java");  
        coursesMap.put(4, "Spring Framework");  
        coursesMap.put(5, "Hibernate ORM framework");  
 
        // 3. 使用 For-each 循环遍历 HashMap  
        for (Map.Entry < Integer, String > entry: coursesMap.entrySet()) {  
            System.out.println(entry.getKey());  
            System.out.println(entry.getValue());  
        }  
    }  
}
 
4. 使用 Lambda 表达式遍历 HashMap
package com.java.tutorials.iterations;  
 
import java.util.HashMap;  
import java.util.Map;  
 
/**  
 * 在 Java 中遍历 HashMap 的5种最佳方法  
 * @author Ramesh Fadatare  
 *  
 */  
public class IterateHashMapExample {  
    public static void main(String[] args) {  
        Map < Integer, String > coursesMap = new HashMap < Integer, String > ();  
        coursesMap.put(1, "C");  
        coursesMap.put(2, "C++");  
        coursesMap.put(3, "Java");  
        coursesMap.put(4, "Spring Framework");  
        coursesMap.put(5, "Hibernate ORM framework");  
 
        // 4. 使用 Lambda 表达式遍历 HashMap  
        coursesMap.forEach((key, value) -> {  
            System.out.println(key);  
            System.out.println(value);  
        });  
    }  
}
 
5. 使用 Stream API 遍历 HashMap
package com.java.tutorials.iterations;  
 
import java.util.HashMap;  
import java.util.Map;  
 
/**  
 * 在 Java 中遍历 HashMap 的5种最佳方法  
 * @author Ramesh Fadatare  
 *  
 */  
public class IterateHashMapExample {  
    public static void main(String[] args) {  
        Map < Integer, String > coursesMap = new HashMap < Integer, String > ();  
        coursesMap.put(1, "C");  
        coursesMap.put(2, "C++");  
        coursesMap.put(3, "Java");  
        coursesMap.put(4, "Spring Framework");  
        coursesMap.put(5, "Hibernate ORM framework");  
 
        // 5. 使用 Stream API 遍历 HashMap  
        coursesMap.entrySet().stream().forEach((entry) - > {  
            System.out.println(entry.getKey());  
            System.out.println(entry.getValue());  
        });  
    }  
}

Arrays.asList()、Collections.singletonList()

Arrays.asList(strArray)返回值是仍然是一个可变的集合,但是返回值是其内部类,不具有add方法,可以通过set方法进行增加值,默认长度是10
Collections.singletonList()返回的是不可变的集合,但是这个长度的集合只有1,可以减少内存空间。但是返回的值依然是Collections的内部实现类,同样没有add的方法,调用add,set方法会报错

如何将一个元素优雅的转换成一个集合

List<K> authcChannels = Stream.of(K).collect(Collectors.toList());

Java没有unsigned类型
Java has been criticized for not supporting unsigned integers. Instead, its byte, short, int, and long types describe signed integers whose values are stored in two’s complement form.

##Random
Random 类位于 java.util 包中,该类常用的有如下两个构造方法。

Random():该构造方法使用一个和当前系统时间对应的数字作为种子数,然后使用这个种子数构造 Random 对象。
Random(long seed):使用单个 long 类型的参数创建一个新的随机数生成器。
在这里插入图片描述
Arrays.binarySearch

java 大整数 BigInteger

在这里插入图片描述
Arrays.setAll() - 设置所有元素

import java.util.Arrays;
 
public class SetAllExample {
    public static void main(String[] args) {
        int[] arrayToSet = new int[5];
        System.out.println("原始数组: " + Arrays.toString(arrayToSet));
        Arrays.setAll(arrayToSet, i -> i * 2);
        System.out.println("设置后的数组: " + Arrays.toString(arrayToSet));
    }
}
输出结果:
原始数组: [0, 0, 0, 0, 0]
设置后的数组: [0, 2, 4, 6, 8]

Arrays.fill()当填充引用类型数组时,所有元素都将引用相同的对象,这可能导致意外的结果。如果需要每个元素都引用不同的对象,请使用循环或Arrays.setAll()来手动创建和分配对象。

Java之Arrays各种方法总结

Java数组相关知识点汇总(含
获得数组中的最小值/最大值/和
List转数组的方法/数组转List
数组求和
数组复制
查找指定元素的位置
已经排好序的数组(Arrays.binarySearch)
打印数组
判断两个数组元素内容是否完全一致
Arrays.fill()和Arrays.setAll()
引用类型数组和泛型)

binarysearch为在指定数组中查找指定值得索引值,该值在范围内找得到则返回该值的索引值,找不到则返回该值的插入位置,如果该值大于指定范围最大值则返回-(maxlength+1),而:

int w=Arrays.binarySearch(a,1,5,8); 查找的范围为索引值1-5,:2,3,4,5,6

8并不在此范围中,且8大于最大索引值的6,所以返回-(5+1):-6
————————————————
版权声明:本文为CSDN博主「普通网友」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/a1439775520/article/details/104307267

Collections.binarysearch

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值