简体   繁体   English

从Int数组中删除重复项[]

[英]Removing Duplicates from Array of Int[]

I have really been struggling with this for an hour or so now. 我真的已经为此挣扎了一个小时左右。 I am trying to remove all the duplicates from an array of int[]. 我正在尝试从int []数组中删除所有重复项。 Every element of the array is a int[] containing the x & y positions of a tile. 数组的每个元素都是一个int [],其中包含图块的x和y位置。 So, the it is [[3, 1], [3, 12], ...]. 因此,它是[[3,1],[3,12],...]。 When generating my world, I add already seen tiles, so I am writing a function to "condense" the tile array. 生成世界时,我添加了已经看到的图块,因此我正在编写一个“压缩”图块数组的函数。

I have tried using a hashSet & set, but for some reason, both DS do not remove the duplicates. 我尝试使用hashSet&set,但是由于某些原因,两个DS都不会删除重复项。 Is there possibly an issue with overriding compare(object1, object2) for int[]'s? 覆盖int []的compare(object1,object2)可能有问题吗?

// Takes array of x,y coordinates (form: int[]{x, y}) and condense it by removing the duplicates //获取x,y坐标数组(形式:int [] {x,y}),并通过删除重复项进行压缩

private int[][] condenseTiles(int[][] tiles) {
    Set<int[]> setOfTiles = new LinkedHashSet<int[]>();

    for(int i = 0; i < tiles.length; i++){
        setOfTiles.add(tiles[i]);
    }

    System.out.println(setOfTiles.size());

    return tiles;
}

I know there are shortcut ways to add every element to a HashSet, but currently nothing is working and I am still seeing duplicates, so I'm just doing it the slow and expanded way. 我知道可以将每个元素添加到HashSet的捷径方法,但是目前没有任何效果,而且仍然看到重复项,因此我只是在缓慢而扩展地进行操作。 For reference, right now, setOfTiles and tiles have the same size no matter what I do. 作为参考,无论我做什么,setOfTiles和tile的大小都相同。 Please let me know if you have any suggestions. 如果您有任何建议,请告诉我。

One possible solution: 一种可能的解决方案:

  • Create a Tile class, one with x and y int fields 创建一个Tile类,其中一个包含x和y int字段
  • Give the class decent public boolean equals(Object o) and public int hashCode() methods, one that regards two Tiles with the same x and y values as being equal and as returning the same hashCode 给类提供体面的public boolean equals(Object o)public int hashCode()方法,该方法将两个具有相同x和y值的Tile视为相等并返回相同的hashCode
  • Place the tiles in a Set<Tile> from the start -- this prevents duplicate entry. 从头开始Set<Tile>放置在Set<Tile> -这样可以防止重复输入。

eg, 例如,

public class Tile {
    private int x;
    private int y;

    public Tile(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Tile other = (Tile) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Tile [" + x + ", " + y + "]";
    }

}

And tested with: 并测试了:

import java.util.LinkedHashSet;
import java.util.Set;

public class TestTile {
    public static void main(String[] args) {
        Set<Tile> tileSet = new LinkedHashSet<>();

        int[][] testData = {{1, 2}, {3, 4}, {5, 6}, {1, 2}, {5, 6}};
        for (int[] pair : testData) {
            Tile tile = new Tile(pair[0], pair[1]);
            tileSet.add(tile);
            System.out.println("Tile added: " + tile);
            System.out.println("All Tiles: ");
            for (Tile t : tileSet) {
                System.out.println("  " + t);
            }
            System.out.println();
        }

    }
}

Which returns: 哪个返回:

Tile added: Tile [1, 2]
All Tiles: 
  Tile [1, 2]

Tile added: Tile [3, 4]
All Tiles: 
  Tile [1, 2]
  Tile [3, 4]

Tile added: Tile [5, 6]
All Tiles: 
  Tile [1, 2]
  Tile [3, 4]
  Tile [5, 6]

Tile added: Tile [1, 2]
All Tiles: 
  Tile [1, 2]
  Tile [3, 4]
  Tile [5, 6]

Tile added: Tile [5, 6]
All Tiles: 
  Tile [1, 2]
  Tile [3, 4]
  Tile [5, 6]

Another possible solution, if you want to use Java 8 streams, note that it has a .filter() method, but this only works with the hashCode and the equals of the objects being streamed, and if you're streaming int arrays by themselves, this simply won't work. 另一个可能的解决方案,如果要使用Java 8流,请注意,它具有.filter()方法,但这仅适用于hashCode和要被流传输的对象的.filter() ,并且如果您自己是通过流传输int数组,这根本行不通。 A work around is to use a wrapper class, similar to this Stack Overflow answer on "Remove duplicates from a list of objects based on property in Java 8" . 一种解决方法是使用包装器类,类似于关于“根据Java 8中的属性从对象列表中删除重复项”的Stack Overflow答案

A wrapper class that might work: 一个可能起作用的包装器类:

import java.util.Arrays;

public class WrapperArray {
    int[] array;

    public WrapperArray(int[] array) {
        this.array = array;
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(array);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        WrapperArray other = (WrapperArray) obj;
        if (!Arrays.equals(array, other.array))
            return false;
        return true;
    }

    public int[] unwrap() {
        return array;
    }
}

And this can be tested like so: 可以这样测试:

import java.util.Arrays;

public class TestTile {
    public static void main(String[] args) {

        int[][] testData = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 1, 2 }, { 5, 6 } };
        System.out.println("before filtering:");
        for (int[] is : testData) {
            System.out.println(Arrays.toString(is));
        }

        int[][] filteredArray = Arrays.stream(testData) // stream int[][] array
                .map(WrapperArray::new)     // map to our wrapper objects
                .distinct()                 // find distinct using wrapper equals/hashCode
                .map(WrapperArray::unwrap)  // convert back to int[]
                .toArray(int[][]::new);     // create new int[][] with results


        System.out.println("after filtering:");
        for (int[] is : filteredArray) {
            System.out.println(Arrays.toString(is));
        }
    }
}

Which returns: 哪个返回:

before filtering:
[1, 2]
[3, 4]
[5, 6]
[1, 2]
[5, 6]
after filtering:
[1, 2]
[3, 4]
[5, 6]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM