Learn to use java Collections tool class with the instance of fighting landlord

catalog

1, Background

Recently, in the process of learning data structure and algorithm, Collections tool class is frequently used, which is a powerful tool in development and simplifies the coding of many related sets. This paper will analyze this tool class in depth through an example.

2, Concept

1. Definition

java.util.Collections
Is a packaging class. It contains a variety of static polymorphic methods for set operations. This class cannot be instantiated, just like a tool class, serving Java's collection framework.

public class Collections {
    // The default constructor is privatized and instantiation is not allowed
    private Collections() {
    }
    ...
}
2. Methods

Collection methods are static methods, which are mainly divided into the following categories: This paper mainly analyzes sorting, find / replace and other methods.

2.1 sorting method
  • Method definition:
// reversal
public static void reverse(List<?> list)
// Random sorting
public static void shuffle(List<?> list) 
// Ascending sort by natural sort
 public static <T> void sort(List<T> list, Comparator<? super T> c)
// Exchange elements at two index locations
public static void swap(List<?> list, int i, int j)
// rotate
public static void rotate(List<?> list, int distance)
2.2 search / replace method
// Dichotomy search
int binarySearch(List<? extends Comparable<? super T>> list, T key)
// According to the custom sorting, return the largest element
int max(Collection coll, Comparator c)
// Return the minimum elements according to the custom sorting
int min(Collection coll, Comparator c)
// Count element occurrences
int frequency(Collection c, Object o),Count element occurrences
// Count the index of the first occurrence of the start in the list
int indexOfSubList(List list, List target)
// Replace old elements with new ones
boolean replaceAll(List list, Object oldVal, Object newVal)

3, An example of fighting against landlords

3.1 code structure

3.2 constant definition
  • Use the way of collection to define the suit, number and king of size of playing cards.
/**
 * Poker constant definition
 *  * @author zhuhuix
 * @date 2020-06-05
 */
public class Constant {

    // Card decors: spades, hearts, clubs, diamonds
    final static List<String> COLORS = new ArrayList<>(
            Arrays.asList(new String[]{"♢", "♣", "♡", "♠"}));
    // Face number
    final static List<String> NUMBERS = new ArrayList<>(
            Arrays.asList(new String[]{"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"}));
    // Wang and Wang
    final static List<String> JOKER = new ArrayList<>(
            Arrays.asList(new String[]{"Xiao Wang","king"}));
}
3.3. Single brand
  • In the definition of a single card class, the compareTo comparison method that will affect the card face size is overridden:
    --If it is a comparison of two cards of "Wang", then "Wang" is greater than "Xiao Wang";
    --If it is a comparison between "Wang" and "digital card", then "Wang" is greater than "digital card";
    --If it is a comparison between "number cards", the card with large number will have large face, and if the numbers are the same, it will be compared according to the pattern (♢)< A kind of < ♡< ♠) (a lt hough the owner does not arrange the size according to the pattern, the program will arrange the cards according to the pattern size.).
/**
 * Single card
 *  * @author zhuhuix
 * @date 2020-06-05
 */
public class Card implements Comparable {

    // Decor
    private String color = "";
    //number
    private String number = "";

    public Card() {
    }

    public Card(String color, String number) {
        this.color = color;
        this.number = number;
    }

    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getNumber() {
        return this.number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return this.color + this.number;
    }

    @Override
    public int compareTo(Object o) {
        if (o instanceof Card) {
            int thisColorIndex = Constant.COLORS.indexOf(this.getColor());
            int anotherColorIndex = Constant.COLORS.indexOf(((Card) o).getColor());
            int thisNumberIndex = Constant.NUMBERS.indexOf(this.getNumber());
            int anotherNumberIndex = Constant.NUMBERS.indexOf(((Card) o).getNumber());

            // Comparison between big Wang and small Wang: big wang is bigger than small Wang
            if ("JOKER".equals(this.color) && "JOKER".equals(((Card) o).getColor())) {
                    return thisColorIndex > anotherColorIndex ? 1 : -1;
            }

            // Comparison between big and small king and digital card: big and small king are greater than digital card
            if ("JOKER".equals(this.color) && !"JOKER".equals(((Card) o).getColor())) {
                return 1;
            }
            if (!"JOKER".equals(this.color) && "JOKER".equals(((Card) o).getColor())) {
                return -1;
            }

            // The number cards are compared with each other: if the number is not equal, the face is large; if the number is equal, the face is large
            if (thisNumberIndex == anotherNumberIndex) {
                return thisColorIndex > anotherColorIndex ? 1 : -1;
            } else {
                return thisNumberIndex > anotherNumberIndex ? 1 : -1;
            }

        } else {
            return -1;
        }
    }
}
3.4 players
  • In the player class, we mainly define the member methods such as grabbing, shuffling, managing, finding, obtaining the maximum and minimum cards, and counting the number of bombs. Among these member methods, we widely use the static methods of the Collections tool class.
/**
 1. game player
 2.  * @author zhuhuix
 3. @date 2020-06-05
 */
public class Player {

    // Player name
    private String name;

    // Player type: farmer / landlord
    private String type;

    // Card caught
    private List<Card> cards;

    public Player(String name, String type) {
        this.name = name;
        this.type = type;
        this.cards = new ArrayList<>();
    }

    // shuffle
    public void shuffle() {
        Collections.shuffle(this.cards);
    }

    // sort
    public void sort() {
        Collections.sort(this.cards, Card::compareTo);
    }

    // Catch a card
    public void draw(Card card) {
        this.cards.add(card);
    }

    // play 
    public void play(Card card) {
        this.cards.remove(card);
    }

    // Find the biggest brand max
    public Card max() {
        return Collections.max(this.cards, Card::compareTo);
    }

    // Find the minimum card min
    public Card min() {
        return Collections.min(this.cards, Card::compareTo);
    }

    // Find the location of the specified card binarySearch
    public int binarySearch(Card card) {
        return Collections.binarySearch(this.cards, card, Card::compareTo);
    }

    // How many bombs are there
    public int frequency() {
        int count = 0;
        List<String> numbers= new ArrayList<>();
        List<String> colors= new ArrayList<>();
        for (int i = 0; i < this.cards.size(); i++) {
            colors.add(this.cards.get(i).getColor());
            numbers.add(this.cards.get(i).getNumber());
        }
        for (int j = 0; j < Constant.NUMBERS.size(); j++) {
            if (Collections.frequency(numbers, Constant.NUMBERS.get(j)) == 4) {
                count++;
            }
        }
        if (Collections.frequency(colors, "JOKER") == 2) {
            count++;
        }
        return count;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public List<Card> getCards() {
        return cards;
    }

    public void setCards(List<Card> cards) {
        this.cards = cards;
    }

    @Override
    public String toString() {
        StringBuilder poker = new StringBuilder("[");
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            poker.append(iterator.next().toString() + ",");
        }
        poker.setCharAt(poker.length() - 1, ']');
        return this.getType() + ":" + this.getName() + "Get it" + this.cards.size() + "Cards:" + poker;
    }
3.5 main program
  1. Generate a whole deck of cards;
  2. Set up 3 players, two of them are farmers and one is landlord;
  3. Three people take turns to hold cards, and the landlord takes three more cards;
  4. The player manages the card to see the card (finds the biggest card and the smallest card);
  5. Judge whether the king is in the hands of the landlord?
  6. How many bombs are there in each player's hands?
/**
 * The main procedure of fighting against landlords
 *
 * @author zhuhuix
 * @date 2020-6-5
 */
public class PlayDemo {

    public static void main(String[] args) {

        // Generate a deck of playing cards
        Poker poker = new Poker();
        System.out.println("Total playing cards" + poker.getCardCount() + "only");

        // Three players, two farmers and one landlord
        int playCount = 3;
        Player player1 = new Player("Player 1", "a farmer");
        Player player2 = new Player("Player 2", "a farmer");
        Player player3 = new Player("Player 3", "landlord");

        // Three players play cards in order
        int i;
        for (i = 0; i < poker.getCardCount() - playCount; i++) {
            if (i % playCount == 0) {
                player1.draw(poker.getCards().get(i));
            } else if (i % playCount == 1) {
                player2.draw(poker.getCards().get(i));
            } else if (i % playCount == 2) {
                player3.draw(poker.getCards().get(i));
            }
        }

        // The landlord takes the remaining cards
        while (i < poker.getCardCount()) {
            player3.draw(poker.getCards().get(i));
            i++;
        }

        // Show the deck and the largest and smallest cards of three players after shuffling
        player1.sort();
        System.out.println(player1.toString());
        System.out.println("The biggest brands are:"+player1.max().toString()+",The smallest card is:"+player1.min().toString());
        player2.sort();
        System.out.println(player2.toString());
        System.out.println("The biggest brands are:"+player2.max().toString()+",The smallest card is:"+player2.min().toString());
        player3.sort();
        System.out.println(player3.toString());
        System.out.println("The biggest brands are:"+player3.max().toString()+",The smallest card is:"+player3.min().toString());

        // Is the king in the hands of the landlord
        if (player3.binarySearch(new Card("JOKER","king"))>=0){
            System.out.println("The king is here"+player3.getType()+player3.getName()+"in the hand");
        }

        // Count how many bombs there are
        System.out.println(player1.getName()+"On hand"+player1.frequency()+"Hand bomb");
        System.out.println(player2.getName()+"On hand"+player2.frequency()+"Hand bomb");
        System.out.println(player3.getName()+"On hand"+player2.frequency()+"Hand bomb");
    }
}

The program output is as follows:

4, In depth understanding

  • We trace the source code of some of these methods
    -- shuffle
 public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
        	//Convert a collection to an array
            Object arr[] = list.toArray();

            //  Random exchange of array element positions by random numbers
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));
			// Assign a scrambled array to a collection through an iterator
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

-- sort

public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
}
    ...
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        //Call the sorting method of array tool class -- this method is the improved merging sorting
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }

-- min/max

public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {
        if (comp==null)
            return (T)min((Collection) coll);

        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();
		// By comparing iterator loops, we find the smallest
        while (i.hasNext()) {
            T next = i.next();
            if (comp.compare(next, candidate) < 0)
                candidate = next;
        }
        return candidate;
 }
 
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
        if (comp==null)
            return (T)max((Collection) coll);

        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();
		// By comparing iterator loops, we find the largest
        while (i.hasNext()) {
            T next = i.next();
            if (comp.compare(next, candidate) > 0)
                candidate = next;
        }
        return candidate;
}

-- binarySearch

public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {
        if (c==null)
            return binarySearch((List<? extends Comparable<? super T>>) list, key);

        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key, c);
        else
            return Collections.iteratorBinarySearch(list, key, c);
    }
    ...
    // Dichotomy search
    private static <T> int iteratorBinarySearch(List<? extends T> l, T key, Comparator<? super T> c) {
        int low = 0;
        int high = l.size()-1;
        ListIterator<? extends T> i = l.listIterator();

        while (low <= high) {
            int mid = (low + high) >>> 1;
            T midVal = get(i, mid);
            int cmp = c.compare(midVal, key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }

Tags: Java

Posted on Fri, 05 Jun 2020 03:10:46 -0400 by trg