【问题标题】:Removing Duplicates from Array of Int[]从 Int[] 数组中删除重复项
【发布时间】:2019-11-14 11:05:55
【问题描述】:

我已经为此苦苦挣扎了一个小时左右。我正在尝试从 int [] 数组中删除所有重复项。数组的每个元素都是一个 int[],其中包含一个图块的 x 和 y 位置。所以,它是 [[3, 1], [3, 12], ...]。在生成我的世界时,我添加了已经看到的图块,所以我正在编写一个函数来“压缩”图块数组。

我尝试过使用 hashSet & set,但由于某种原因,两个 DS 都不会删除重复项。为 int[] 覆盖 compare(object1, object2) 是否可能存在问题?

// 获取 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;
}

我知道有一些快捷方式可以将每个元素添加到 HashSet,但目前没有任何效果,而且我仍然看到重复项,所以我只是以缓慢和扩展的方式来做。作为参考,现在,无论我做什么,setOfTiles 和tiles 的大小都是相同的。如果您有任何建议,请告诉我。

【问题讨论】:

  • 请参阅我的答案的补充。如果您有任何问题或希望提供任何反馈,请发表评论。

标签: java arrays duplicates set


【解决方案1】:

一种可能的解决方案:

  • 创建一个 Tile 类,其中包含 x 和 y int 字段
  • 为类提供像样的public boolean equals(Object o)public int hashCode() 方法,一种将具有相同x 和y 值的两个Tiles 视为相等并返回相同hashCode 的方法
  • 从一开始就将磁贴放在Set&lt;Tile&gt; 中——这样可以防止重复输入。

例如,

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 + "]";
    }

}

并通过以下方式测试:

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();
        }

    }
}

返回:

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]

另一种可能的解决方案,如果您想使用 Java 8 流,请注意它有一个 .filter() 方法,但这仅适用于正在流式传输的对象的 hashCode 和 equals,并且如果您正在流式传输 int 数组靠他们自己,这根本行不通。一种解决方法是使用包装类,类似于this Stack Overflow answer on "Remove duplicates from a list of objects based on property in Java 8"

一个可能工作的包装类:

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;
    }
}

可以这样测试:

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));
        }
    }
}

返回:

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

【讨论】:

    猜你喜欢
    • 2016-10-17
    • 2011-06-29
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    相关资源
    最近更新 更多