Java simple solution with explanation (using priority queue)
Please upvote if you like the solution\n\n\nclass Solution {\n    \n   /**\n     * Get all the values of the perimeter and out of those value get the min value 
### Please upvote if you like the solution\n\n```\nclass Solution {\n    \n   /**\n     * Get all the values of the perimeter and out of those value get the min value and try to explore its neighbour.\n     * Each time we get the minValue we try to calculate the volume of water it can hold off.\n     */\n    public int trapRainWater(int[][] grid) {\n\n        int rowLength = grid.length;\n        int colLength = grid[0].length;\n\n        boolean[][] visited = new boolean[rowLength][colLength];\n\n        // Min Heap because we want the lowest height always to calculate the water volume.\n        Queue<Pair> minHeap = new PriorityQueue<>(new Comparator<Pair>() {\n            @Override\n            public int compare(Pair obj1, Pair obj2) {\n                return obj1.height - obj2.height;\n            }\n        });\n\n\n        /*\n         * Adding the perimeter values to the minHeap because we want the minimum value it has.\n         * So that we can traverse inwards to figure out that which all position are less that this value which can hold water.\n         */\n        for (int i = 0; i < rowLength; i++) {\n            for (int j = 0; j < colLength; j++) {\n                if (i == 0 || i == rowLength - 1 || j == 0 || j == colLength - 1) {\n                    minHeap.add(new Pair(grid[i][j], i, j));\n                    visited[i][j] = true;\n                }\n            }\n        }\n\n        int volume = 0;\n        int maxHeightEdge = Integer.MIN_VALUE;\n\n        while (!minHeap.isEmpty()) {\n            Pair current = minHeap.poll();\n            int currentRow = current.row;\n            int currentCol = current.col;\n            // Getting the current max height\n            maxHeightEdge = Math.max(maxHeightEdge, current.height);\n            volume += maxHeightEdge - current.height;\n\n            /*\n             * Explore its unvisited neighbour of the current pair, is its a valid position add it to the queue\n             * along with mark it as visited\n             */\n\n            // Left One\n            if (isValidPosition(grid, currentRow, currentCol - 1, rowLength, colLength, visited)) {\n                visited[currentRow][currentCol - 1] = true;\n                minHeap.add(new Pair(grid[currentRow][currentCol - 1], currentRow, currentCol - 1));\n            }\n\n            // Right One\n            if (isValidPosition(grid, currentRow, currentCol + 1, rowLength, colLength, visited)) {\n                visited[currentRow][currentCol + 1] = true;\n                minHeap.add(new Pair(grid[currentRow][currentCol + 1], currentRow, currentCol + 1));\n            }\n\n            // Up One\n            if (isValidPosition(grid, currentRow - 1, currentCol, rowLength, colLength, visited)) {\n                visited[currentRow - 1][currentCol] = true;\n                minHeap.add(new Pair(grid[currentRow - 1][currentCol], currentRow - 1, currentCol));\n            }\n\n            // Down One\n            if (isValidPosition(grid, currentRow + 1, currentCol, rowLength, colLength, visited)) {\n                visited[currentRow + 1][currentCol] = true;\n                minHeap.add(new Pair(grid[currentRow + 1][currentCol], currentRow + 1, currentCol));\n            }\n        }\n\n        return volume;\n    }\n\n    /**\n     * Just to check whether the position is valid or not.\n     */\n    public boolean isValidPosition(int[][] grid, int row, int col, int rowLength, int colLength, boolean[][] visited) {\n\n        if (row < 0 || row >= rowLength || col < 0 || col >= colLength || visited[row][col]) {\n            return false;\n        }\n\n        return true;\n    }\n    \n    \n    /*\n     * Utility Class to hold the any position\'s height and its position\n     */\n    class Pair {\n        public int height;\n        public int row;\n        public int col;\n\n        public Pair(int height, int row, int col) {\n            this.height = height;\n            this.row = row;\n            this.col = col;\n        }\n    }\n}\n```
[]