Java Generics: Useing multiple generic types in one collection type
I would like to use two generic types as a key for a hash map. Effectively:
Map<CollectionType<Integer, Integer>, Character> map = new HashMap<>();
I am trying to find if this is possible, and if so which collection type I could use. The right type needs to be able to accept duplicate values. i.e. <1, 0>, <1, 1>, <2, 0> could all be used as a key in the map
for additional background the key in the map will be coordinates on a hex grid, and the value is what is currently stored at that location.
1 answer
-
answered 2018-11-20 03:46
Kartik
Use a
Pair<Integer, Integer>
, provided by many libraries like inorg.apache.commons.lang3.tuple.Pair
or in jdk asjavafx.util.Pair
.equals()
andhashcode()
are overridden, so it can work as a key in the Map.Map<Pair<Integer, Integer>, Character> map = new HashMap<>();
See also questions close to this topic
-
Returning values from @Bean methods
What happens to the object I return from an @Bean method? Is there anyway to retrieve this object from another class?
-
Having Problem With Click Listener in Java
I'm making a chess-like game in java and I'm having an issue with the click events. The
mouseClicked
function isn't responding to my clicks on the window and for no apparent reason.I have already tried a few things such as changing class names and using different functions but nothing has worked.
package main.game.com; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class ClickEvent extends MouseAdapter { public void mouseClicked(MouseEvent e) { System.out.println("hello"); } }
package main.game.com; import java.awt.Canvas; public class Main extends Canvas { private static final long serialVersionUID = 1673528055664762143L; private static final int WIDTH = 416, HEIGHT = 439; public Main() { Window window = new Window(WIDTH, HEIGHT, "DARRAGH", this); this.addMouseListener(new ClickEvent()); }
package main.game.com; import java.awt.Canvas; import java.awt.Dimension; import javax.swing.JFrame; public class Window extends Canvas { private static final long serialVersionUID = 6733885629776844621L; public Window(int width, int height, String title, Main main) { JFrame frame = new JFrame(title); frame.setPreferredSize(new Dimension(width, height)); frame.setMaximumSize(new Dimension(width, height)); frame.setMinimumSize(new Dimension(width, height)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.add(main); frame.setVisible(true); main.start(); } }
The first set of code is my
mouseAdapter
library and the second is the first part of my main class containing theclickListener
. -
JDBC choose NIC to use based on local ip address?
I'm using the PostgreSQL JDBC Driver on a machine that has multiple network cards. Only one of them has a stable connection. Is there anyway to tell JDBC to use that NIC by giving it the IP address of the NIC?
-
C# generic utility to check JSON string for anonymous type
I have a JSON string. I want to check if it contains an anonymous object. If it does then return the value. If it doesn't then return a default value. I then want to be able to repeat this multiple times for different anonymous objects.
Here is a sample of the code that I have currently implemented but obviously it is duplicated each time and not very "clean".
var displayDataBy = 0; var displayDataByDefinition = new { DisplayDataBy = new { Key = "string", Value = displayDataBy } }; var displayDataByResult = JsonConvert.DeserializeAnonymousType(this.OhdContentPageParameters, displayDataByDefinition); try { displayDataBy = displayDataByResult.DisplayDataBy.Value; } catch { } var xMinsOeeToShow = 480; var xMinsOeeToShowDefinition = new { XMinsOeeToShow = new { Key = "string", Value = xMinsOeeToShow } }; var xMinsOeeToShowResult = JsonConvert.DeserializeAnonymousType(this.OhdContentPageParameters, xMinsOeeToShowDefinition); try { xMinsOeeToShow = xMinsOeeToShowResult.XMinsOeeToShow.Value; } catch { }
I would prefer it was a generic method that I could call for each anonymous type. Also it would be nice to not have to rely on the try/catch. Can it be done?
UPDATE...
This is working great for int, bool and double:
public static T2 DeserializeValue<T, T2>(this string json, T definition, T2 defaultValue, Func<T, T2?> getValueFunc) where T2 : struct { var jsonAnon = JsonConvert.DeserializeAnonymousType(json, definition); return getValueFunc(jsonAnon) ?? defaultValue; }
I added this for strings:
public static string DeserializeStringValue<T>(this string json, T definition, string defaultValue, Func<T, string> getValueFunc) { var jsonAnon = JsonConvert.DeserializeAnonymousType(json, definition); return getValueFunc(jsonAnon) ?? defaultValue; }
-
Resolving a list of classes that implement generic interface and abstract class with Autofac
I am trying to resolve strategy pattern using a factory. This factory generates an open generic interface. It depends on an IEnumerable of that generic interface. I can obtain an IEnumerable of non-generic to work, but with generics i get an empty list.
I can also resolve the class directly, but not the list.
An additional caveat is that we could have potentially unlimited Repositories, so registering them individually would be painful.
I've tried these ways to register with Autofac
var dataAccess = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyTypes(dataAccess).AsClosedTypesOf(typeof(Repositories.IRepository<>)); builder.RegisterAssemblyTypes(dataAccess) .Where(t => IsAssignableToGenericType(t, typeof(Repositories.IRepository<>)) && !t.IsAbstract && !t.IsInterface) .AsImplementedInterfaces(); builder.RegisterAssemblyTypes(dataAccess) .Where(t => IsAssignableToGenericType(t, typeof(Repositories.IRepository<>)) && !t.IsAbstract && !t.IsInterface);
public interface IRepository<T> where T : BaseProcessorType { Task Add(T data); } public abstract class BaseRepository<T> : IRepository<T> where T : BaseProcessorType { public async Task Add(T data) { // something } } public class ActivityRepository : BaseRepository<Activity>, IRepository<Activity> { public ActivityRepository() : base() { } public override async Task Add(Activity data) { // override } }
Then I would like to to resolve
var lol = something.Resolve<IEnumerable<Repositories.IRepository<BaseProcessorType>>>();
But unfortunately this returns an empty list of IRepositories.
-
How do I make a generic absolute value function?
I'm attempting to write a generic function that calculates the absolute value of any signed integer type. It should return an error when the value is the lowest possible negative value, e.g for 8 bits
abs(-128)
cannot be represented.I got this working for
i8
:pub fn abs(x: i8) -> Result<i8, String> { match x { x if x == -128i8 => Err("Overflow".to_string()), // I know could just use x.abs() now but this illustrates a problem in the generic version below... x if x < 0i8 => Ok(-x), _ => Ok(x), } } fn main() { println!("{:?}", abs(-127i8)); println!("{:?}", abs(-128i8)); }
I can't get the generic version to work. Specifically I've two problems:
- How do I generically determine the minimum value? What is the Rust equivalent of the C++
std::numeric_limits<T>::min()
? There is e.g.std::i32::MIN
but I can't writestd::T::MIN
. - My generic implementation errors on the match arm for negative values with "cannot bind by-move into a pattern guard" (yet the non-generic version doesn't.)
use num::{traits::Zero, Integer, Signed}; // 0.2.0 pub fn abs<T>(x: T) -> Result<T, String> where T: Signed + Integer + Zero, { match x { //x if x == ***rust equivalent of std::numeric_limits<T>::min()** => Err("Overflow".to_string()), x if x < T::zero() => Ok(-x), _ => Ok(x), } } fn main() { println!("{:?}", abs(-127i8)); println!("{:?}", abs(-128i8)); }
error[E0008]: cannot bind by-move into a pattern guard --> src/main.rs:9:9 | 9 | x if x < T::zero() => Ok(-x), | ^ moves value into pattern guard
- How do I generically determine the minimum value? What is the Rust equivalent of the C++
-
How to update all the values in a BTreeSet?
I have collection which is a field in a struct in some module. I want to update all the values in the collection from another module.
I wrote some code to mimic what I want to achieve. It's shortened a bit, but I think it has all needed parts. There is no struct holding the collection in this code, but imagine this is a getter which returns the collection. I added in comments how I think it should look.
pub mod pos { use std::cmp::{Ordering, PartialEq}; #[derive(PartialOrd, PartialEq, Eq, Hash, Debug, Copy, Clone)] pub struct Pos { pub x: i32, pub y: i32, } #[allow(dead_code)] impl Pos { pub fn of(x: i32, y: i32) -> Self { Self { x, y } } pub fn offset(&mut self, pos: &Self) -> Self { self.x += pos.x; self.y += pos.y; *self } } impl Ord for Pos { fn cmp(&self, other: &Self) -> Ordering { if self.x < other.x { Ordering::Less } else if self.eq(other) { Ordering::Equal } else { Ordering::Greater } } } } mod test { use crate::pos::Pos; use std::collections::BTreeSet; #[test] fn test_iterators() { let mut data_in_some_strct: BTreeSet<Pos> = BTreeSet::new(); data_in_some_strct.insert(Pos::of(1, 1)); data_in_some_strct.insert(Pos::of(2, 2)); data_in_some_strct.insert(Pos::of(3, 3)); data_in_some_strct.insert(Pos::of(4, 4)); // mimic getter call ( get_data(&mut self) -> &BTreeSet<Pos> {...} // let set = data_in_some_strct; // works, but not a reference let set = &data_in_some_strct; // doesn't work, How to adjust code to make it work?? data_in_some_strct = set .into_iter() .map(|mut p| p.offset(&Pos::of(1, 0))) .inspect(|p| println!("{:?}", *p)) .collect(); assert_eq!(data_in_some_strct.contains(&Pos::of(2, 1)), true); assert_eq!(data_in_some_strct.contains(&Pos::of(3, 2)), true); assert_eq!(data_in_some_strct.contains(&Pos::of(4, 3)), true); assert_eq!(data_in_some_strct.contains(&Pos::of(5, 4)), true); } }
error[E0596]: cannot borrow `*p` as mutable, as it is behind a `&` reference --> src/lib.rs:56:26 | 56 | .map(|mut p| p.offset(&Pos::of(1, 0))) | - ^ `p` is a `&` reference, so the data it refers to cannot be borrowed as mutable | | | help: consider changing this to be a mutable reference: `&mut pos::Pos`
I managed to make it work without borrowing, but I would like to make it work with borrowing. I guess there is more then one way to achieve it. Comments to help my Rust brain dendrites connect are welcome.
-
Is it possible to get the item index using Contains?
When I use
if (moscowCars.Contains(cars[x].Name))
it founds the value in a collection and I believe that not necessary to usemoscowCars.RemoveAt(moscowCars.FindIndex(o => o.Equals(cars[x].Name)));
to find it for a second time, just:moscowCars.Remove(cars[x].Name);
. Of course, I can usetry & catch
instead ofif
, but I just want to know can I get the item index usingContains
?using System.Collections.Generic; namespace Autoworld { class GoodCars { static List<Tech> cars = new List<Tech>(); public class Tech { public string Name { get; set; } public double KM { get; set; } } static void Main() { List<string> moscowCars = new List<string> { "GAZ-330811 Aper", "Lada Vesta Sport" }; cars.Add(new Tech() { Name = "Lada Vesta Sport", KM = 190 }); for (int x = 0; x < cars.Count; x++) { if (moscowCars.Contains(cars[x].Name)) { moscowCars.RemoveAt(moscowCars.FindIndex(o => o.Equals(cars[x].Name))); } } } } }
-
Laravel Marge & Map problems
I have two kinds of problems that I'm trying to fix.
First thing:
One of them is using merge to combine two objects together in order to get rid of duplication of lines:$lead -> foreach of $leads = Lead::all(); $tempUser = DB::table('users') ->select('phone','email', DB::raw('CONCAT(users.first_name, " ", users.last_name) AS name')) ->where('id', $lead->customer_id) ->first(); $lead->name = $tempUser->name; $lead->phone = $tempUser->phone; $lead->email = $tempUser->email;
searching for a way using a merge function to get rid of this 3 lines:
$lead->name = $tempUser->name; $lead->phone = $tempUser->phone; $lead->email = $tempUser->email;
Second thing:
I'm trying to use map function in order to make an array of users list for the selection field. It makes me an array in another array and I don't have any idea how to get rid of it.$mailingLists = MailingList::select('id', 'name')->get(); $lists = collect($mailingLists)->map(function($mailingLists){ return [$mailingLists->id => $mailingLists->name]; })->toArray();
Output:
Array ( [0] => Array ( [1] => Mailing List ) [1] => Array ( [3] => Mailing List 2 ) )
desire:
Array ( [1] => Mailing List [3] => Mailing List 2 )
Thanks for the help & support...!